/* ============================================================
   GT CRM — shared design-system foundation
   v1.5.53 — enterprise CSS base
   ============================================================ */

/* T18-57: self-hosted Inter (variable) for the premium mechanic UI. woff2 only,
   no external CDN at runtime. Applied via --mi-font (mechanic theme only). */
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url('/static/fonts/inter-cyrillic.woff2') format('woff2');
  unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
}
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url('/static/fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

:root {
  /* Brand palette (preserved) — DS-1A: values now sourced from the
     reference layer (tokens.css), loaded before this file; every value
     below is byte-identical to before this stage, only re-expressed via
     var(--gt-ref-*) instead of an embedded hex literal. */
  --gt-black:     var(--gt-ref-black);
  --gt-graphite:  var(--gt-ref-graphite);
  --gt-brand-red: var(--gt-ref-brand-red);   /* GT brand accent only (logo / header accent line) */
  --gt-red:       var(--gt-ref-brand-red);   /* legacy alias — do NOT use as primary UI color */
  --gt-light:     var(--gt-ref-neutral-100);
  --gt-border:    var(--gt-ref-neutral-200);
  --gt-gray:      var(--gt-ref-neutral-400);

  /* Workspace tokens */
  --gt-bg:           var(--gt-ref-workspace-bg);
  --gt-surface:      var(--gt-ref-workspace-surface);
  --gt-surface-muted:var(--gt-ref-workspace-surface-muted);
  --gt-text:         var(--gt-ref-workspace-text);
  --gt-muted:        var(--gt-ref-neutral-400);

  /* Primary — calm enterprise blue (primary workflow actions/active/focus) */
  --gt-primary: var(--gt-ref-blue-600);
  --gt-primary-hover: var(--gt-ref-blue-800);
  --gt-primary-soft: var(--gt-ref-blue-50);

  /* Status palette — semantic roles */
  --gt-blue:       var(--gt-ref-blue-600);
  --gt-green:      var(--gt-ref-green-600);
  --gt-orange:     var(--gt-ref-orange-600);

  --gt-success:    var(--gt-ref-green-600);
  --gt-success-bg: var(--gt-ref-green-bg);
  --gt-warning:    var(--gt-ref-orange-600);
  --gt-warning-bg: var(--gt-ref-orange-bg);
  --gt-danger:     var(--gt-ref-red-600);
  --gt-danger-bg:  var(--gt-ref-red-bg);
  --gt-info-bg:    var(--gt-ref-blue-eff);
  --gt-neutral-bg: var(--gt-ref-neutral-bg);

  /* Elevation */
  --gt-shadow-sm:  0 1px 3px rgba(0,0,0,.07), 0 1px 2px rgba(0,0,0,.05);
  --gt-shadow-md:  0 4px 12px rgba(0,0,0,.08), 0 2px 4px rgba(0,0,0,.04);

  /* Radii */
  --gt-radius-sm: 6px;
  --gt-radius:    10px;
  --gt-radius-lg: 14px;

  /* Focus ring — primary blue */
  --gt-focus: 0 0 0 3px rgba(37, 99, 235, 0.25);

  /* ── T18-17B: Semantic token layer ─────────────────────────── */
  /* Action accent — calm blue lineage; --gt-brand-red is logo/header only, never UI action */
  --gt-accent:        var(--gt-primary);
  --gt-accent-hover:  var(--gt-primary-hover);
  --gt-accent-soft:   var(--gt-primary-soft);

  /* Text scale */
  --gt-text-muted:    var(--gt-muted);
  --gt-text-soft:     var(--gt-ref-slate-600);

  /* Second surface elevation */
  --gt-surface-2:     var(--gt-ref-slate-100);

  /* Focus ring alias */
  --gt-focus-ring:    var(--gt-focus);

  /* Radius additions */
  --gt-radius-md:     var(--gt-radius);          /* 10px */
  --gt-radius-xl:     22px;

  /* Spacing scale */
  --gt-space-1: .25rem;
  --gt-space-2: .5rem;
  --gt-space-3: .75rem;
  --gt-space-4: 1rem;
  --gt-space-5: 1.25rem;
  --gt-space-6: 1.5rem;
  --gt-space-8: 2rem;

  /* Control heights */
  --gt-control-h:     48px;
  --gt-control-h-lg:  56px;
  --gt-btn-h-primary: 56px;

  /* ── DS-1B: shared component tokens (action/feedback primitives) ────
     Secondary/success/danger button variants, badges, and notice/alert/
     callout/ok/warning states — sourced from tokens.css's reference layer,
     same values the app already ships (Porcelain-preserving default).
     Only --gt-btn-secondary-*, --gt-btn-secondary-fg, --gt-state-*-fg/
     -border, and --gt-badge-neutral-bg get a .theme-dark-desktop override
     below; the solid success/danger button fills and focus rings are kept
     deliberately theme-neutral (a saturated CTA fill that already works on
     both light and dark canvases, unchanged either way — a defensible reuse
     of the existing accepted color rather than a new dark invention). */
  --gt-state-info-fg:           var(--gt-ref-state-info-fg);
  --gt-state-info-border:       var(--gt-ref-state-info-border);
  --gt-state-success-fg:        var(--gt-ref-state-success-fg);
  --gt-state-success-border:    var(--gt-ref-state-success-border);
  --gt-state-danger-fg:         var(--gt-ref-state-danger-fg);
  --gt-state-danger-border:     var(--gt-ref-state-danger-border);
  --gt-state-warning-fg:        var(--gt-ref-state-warning-fg);
  --gt-state-warning-border:    var(--gt-ref-state-warning-border);

  --gt-btn-secondary-bg:        var(--gt-ref-btn-secondary-bg);
  --gt-btn-secondary-bg-hover:  var(--gt-ref-btn-secondary-bg-hover);
  --gt-btn-secondary-fg:        var(--gt-graphite);
  --gt-btn-success-bg-hover:    var(--gt-ref-btn-success-bg-hover);
  --gt-btn-success-focus-ring:  rgba(22,163,74,.3);
  --gt-btn-danger-bg:           var(--gt-ref-btn-danger-bg);
  --gt-btn-danger-bg-hover:     var(--gt-ref-btn-danger-bg-hover);
  --gt-btn-danger-focus-ring:   rgba(220,38,38,.3);
  --gt-btn-solid-fg:            var(--gt-ref-btn-solid-fg);

  --gt-badge-neutral-bg:        var(--gt-ref-badge-neutral-bg);

  /* ── DS-1C: desktop header/nav shell tokens ──────────────────────────
     .header is deliberately always-dark slate regardless of the
     Porcelain/Studio+Command toggle (see .header's own pre-existing
     comment below) — no .theme-light/.theme-dark-desktop override here,
     by design, matching that existing behavior exactly. */
  --gt-shell-bg:             var(--gt-ref-shell-bg);
  --gt-shell-text:           var(--gt-ref-shell-text);
  --gt-shell-border:         var(--gt-ref-shell-border);
  --gt-shell-label-fg:       var(--gt-ref-shell-label-fg);
  --gt-shell-label-border:   var(--gt-ref-shell-label-border);
  --gt-shell-nav-fg:         var(--gt-ref-shell-nav-fg);
  --gt-shell-nav-fg-hover:   var(--gt-ref-shell-nav-fg-hover);
  --gt-shell-nav-bg-hover:   rgba(255, 255, 255, .08);
  --gt-shell-nav-bg-active:  rgba(255, 255, 255, .12);

  /* ── DS-1D: shared table chrome tokens ───────────────────────────────
     Porcelain-preserving defaults here (root); Studio+Command gets a
     genuinely different, readable dark table below, unlike the always-
     dark DS-1C shell — table chrome DOES switch with the page theme. */
  --gt-table-header-bg:      var(--gt-ref-table-header-bg);
  --gt-table-header-fg:      var(--gt-ref-table-header-fg);
  --gt-table-row-border:     var(--gt-ref-neutral-bg);

  /* ── DS-1E: shared form-control focus tokens ─────────────────────────
     input/select/textarea's base style already used only tokens
     (--gt-border/--gt-surface/--gt-text, all theme-switched since DS-1A)
     — the one gap was the FOCUS state, which used the root-only,
     never-switched --gt-primary/--gt-focus (Studio+Command kept the same
     flat blue-600 ring regardless of theme, unlike newer components like
     .rc-input/.ro-search-input which already use --gt-accent/--gt-focus-
     ring). Porcelain-preserving defaults here (root) are literal aliases
     of the CURRENT --gt-primary/--gt-focus values — zero visual change;
     Studio+Command below reuses those same newer, already-accepted
     tokens instead of inventing anything new. */
  --gt-form-focus-border:    var(--gt-primary);
  --gt-form-focus-ring:      var(--gt-focus);

  /* ── DS-1F: deferred item 132 resolver — remaining shared interactive-state tokens ──
     Two usage classes, deliberately handled differently:
     (1) TEXT/border/outline accents (link color, border-left accent,
     checkbox outline) — safe to theme-switch: Studio's light accent blue
     reads at 7.6-8.4:1 against every Studio surface.
     (2) SOLID FILL + white text pairings (.btn/.btn-primary background,
     .item-check:checked's fill under its white checkmark icon,
     .quick-btn.active/.filters a.active's fill under literal white text)
     — kept DELIBERATELY theme-neutral, same as DS-1B's .btn-success/
     .btn-danger: white text on Studio's light accent blue measures
     only ~2.16:1, a real WCAG failure — switching these would introduce a
     new accessibility regression this stage must not create. Porcelain-
     preserving defaults here are literal aliases of the current values —
     zero visual change to either theme's current button appearance. */
  --gt-interactive-accent:      var(--gt-primary);
  --gt-interactive-focus-ring:  var(--gt-focus);
  --gt-btn-primary-focus-ring:  0 0 0 3px var(--gt-ref-btn-primary-focus-ring);

  --gt-solid-accent-bg:         var(--gt-primary);
  --gt-solid-accent-bg-hover:   var(--gt-primary-hover);
  /* PATH08-RECEPTION-OWNER-IMPLEMENTATION-FIDELITY-01: the edge of a field or an outlined button. The same as
     --gt-border everywhere except the light desk, which binds its own (see .theme-light). */
  --gt-field-border:            var(--gt-border);

  /* Deferred item 133 resolver: `.filters a:hover`'s border-color only.
     Porcelain-preserving default here; Studio+Command below derives a
     genuinely readable hover-emphasis shade from the ALREADY WCAG-verified
     (deferred item 129) --gt-ref-studio-border anchor — no new dark color
     is fabricated. */
  --gt-filter-hover-border:     var(--gt-ref-filter-hover-border);

  /* ── .toast / .splus-status-badge tokenization ───────────────────────
     .toast is DELIBERATELY theme-invariant (no .theme-dark-desktop
     override below) — its background/text already exactly match the
     always-dark shell's own tone (--gt-ref-shell-bg / --gt-ref-btn-solid-
     fg), a fixed-position overlay notification meant to stand out the
     same way regardless of page theme, matching the established shell
     precedent (DS-1C) rather than switching. Porcelain-preserving
     defaults below for the badge states; Studio+Command overrides sit in
     .theme-dark-desktop further down, reusing already-accepted anchors. */
  --gt-toast-bg:                 var(--gt-ref-shell-bg);
  --gt-toast-fg:                 var(--gt-ref-btn-solid-fg);

  --gt-splus-badge-neutral-bg:   var(--gt-ref-neutral-bg);
  --gt-splus-badge-neutral-fg:   var(--gt-ref-splus-badge-neutral-fg);
  --gt-splus-badge-ok-bg:        var(--gt-ref-green-bg);
  --gt-splus-badge-warn-bg:      var(--gt-ref-orange-bg);
  --gt-splus-badge-warn-fg:      var(--gt-ref-splus-badge-warn-fg);
  --gt-splus-badge-blocked-bg:   var(--gt-ref-red-bg);
  --gt-splus-badge-blocked-fg:   var(--gt-ref-btn-danger-bg-hover);

  /* ── T18-11E receptionist inspection-results tokens ──────────────────
     Porcelain-preserving defaults (byte-copies of the current raw values,
     reusing existing reference tokens wherever an exact match exists —
     see tokens.css for the trace). Studio+Command overrides sit in
     .theme-dark-desktop further down. */
  --gt-result-neutral-bg:              var(--gt-ref-neutral-bg);
  --gt-result-neutral-fg:              var(--gt-ref-splus-badge-neutral-fg);
  --gt-result-ok-badge-bg:             var(--gt-ref-result-ok-badge-bg);
  --gt-result-ok-fg:                   var(--gt-ref-result-ok-fg);
  --gt-result-issue-badge-bg:          var(--gt-ref-result-issue-badge-bg);
  --gt-result-issue-fg:                var(--gt-ref-btn-danger-bg-hover);
  --gt-result-skip-fg:                 var(--gt-ref-neutral-400);
  --gt-result-skipped-badge-bg:        var(--gt-ref-result-skipped-badge-bg);
  --gt-result-skipped-badge-fg:        var(--gt-ref-blue-800);
  --gt-result-state-skipped-fg:        var(--gt-ref-blue-600);
  --gt-result-na-badge-bg:             var(--gt-ref-result-na-badge-bg);
  --gt-result-na-fg:                   var(--gt-ref-result-na-fg);
  --gt-result-item-ok-border:          var(--gt-ref-green-600);
  --gt-result-item-issue-border:       var(--gt-ref-red-600);
  --gt-result-item-issue-bg:           var(--gt-ref-result-item-issue-bg);
  --gt-result-item-not-checked-border: var(--gt-ref-result-item-not-checked-border);
  --gt-result-item-skipped-border:     var(--gt-ref-result-item-skipped-border);
  --gt-result-item-skipped-bg:         var(--gt-ref-blue-eff);
  --gt-result-item-na-border:          var(--gt-ref-result-item-na-border);
  --gt-result-item-na-bg:              var(--gt-ref-result-item-na-bg);
  --gt-photo-thumb-border:             var(--gt-ref-photo-thumb-border);
  --gt-result-all-clear-bg:            var(--gt-ref-result-all-clear-bg);
  --gt-result-all-clear-fg:            var(--gt-ref-result-all-clear-fg);

  /* ── DS-1 package 1: reception list/detail/results (2026-07-17) ──────
     IMPORTANT correction made during this stage's own verification (the
     checker's fail-before/pass-after proof caught it): --gt-accent and
     --gt-danger are NOT theme-neutral — .theme-light overrides them to
     the Porcelain-specific --gt-ref-porcelain-accent/-danger, distinct
     from --gt-primary/--gt-ref-btn-danger-bg (which back the genuinely
     theme-neutral --gt-solid-accent-bg/--gt-btn-danger-bg DS-1F uses
     elsewhere). So --gt-accent-solid-fg/--gt-danger-solid-fg (the text
     sitting on .ro-filter.is-active/.ro-filter-decide.is-active/
     .ro-cal-day.is-edge's FLAT --gt-accent/--gt-danger fills, which stay
     UNCHANGED/theme-switched here — reverting an earlier draft of this
     stage that incorrectly swapped them to the theme-neutral tokens and
     would have changed Porcelain's rendered color) DO switch below:
     Porcelain keeps the current near-white; Studio needs a DARK text
     instead, since Studio's accent/danger are light colors (--gt-ref-
     studio-accent/-danger). --gt-cta-solid-fg/--gt-lightbox-text stay
     genuinely theme-neutral (both reuse the same Porcelain-preserving
     reference value) — see their own consumers' comments for why. */
  --gt-cta-gradient-top:        var(--gt-ref-cta-gradient-top);
  --gt-cta-gradient-top-hover:  var(--gt-ref-cta-gradient-top-hover);
  --gt-accent-solid-fg:         var(--gt-ref-accent-solid-fg);
  --gt-danger-solid-fg:         var(--gt-ref-danger-solid-fg);
  /* Update (2026-07-17, resolves deferred item 140): .rc-btn-primary's CTA
     gradient (fixed top stop into --gt-accent's theme-switching bottom
     stop, logged here as a borderline/poor-contrast pre-existing
     characteristic) has been replaced by the owner-approved flat
     deep-blue treatment — see .rc-btn-primary's own rule for the new
     theme-neutral solid fill (--gt-solid-accent-bg, already existing,
     no new token). --gt-cta-gradient-top(-hover) above are now UNUSED
     (no consumer) — left in place, not deleted, since removing a token
     declaration was out of this stage's scope ("do not change tokens").
     --gt-cta-solid-fg is still used, now paired with the flat fill
     instead of the old gradient's top stop; still theme-neutral,
     clearing 4.5:1 in both themes since the fill no longer switches. */
  --gt-cta-solid-fg:            var(--gt-ref-accent-solid-fg);
  /* .rw-lightbox-pos sits on a fixed always-dark rgba() overlay
     (theme-invariant, same family as .toast/.nav) — its text stays
     near-white regardless of desktop theme, unrelated to --gt-accent. */
  --gt-lightbox-text:           var(--gt-ref-accent-solid-fg);
  --gt-status-draft-chip-bg:    var(--gt-ref-status-draft-chip-bg);
  --gt-status-draft-chip-fg:    var(--gt-ref-status-draft-chip-fg);
  --gt-status-draft-accent:     var(--gt-ref-status-draft-accent);
  --gt-status-cancelled-accent: var(--gt-ref-status-cancelled-accent);
  --gt-status-annulled-accent:  var(--gt-ref-status-annulled-accent);
  --gt-status-admin-chip-bg:    var(--gt-ref-status-admin-chip-bg);
  --gt-status-admin-chip-fg:    var(--gt-ref-status-admin-chip-fg);
  --gt-results-widget-issue-bg: var(--gt-ref-results-widget-issue-bg);

  /* ── DS-1 package 2: shared desktop status/notice/intake/primary-
     action primitives (2026-07-17) ──────────────────────────────────
     .insp-status-in_progress's text already matched the existing
     --gt-state-warning-fg exactly (reused directly, no change here);
     only its background is genuinely new. .btn-primary:hover's
     background is a distinct historical shade, kept DELIBERATELY
     theme-neutral below (no .theme-dark-desktop override) — the base
     .btn-primary state's fill stays var(--gt-accent) (theme-switching,
     UNCHANGED, Porcelain-preserving), so only ITS text
     (--gt-btn-primary-fg) needs to switch; the :hover state instead
     explicitly reverts color back to the existing theme-neutral
     --gt-btn-solid-fg (white, matching current behavior exactly),
     avoiding the contrast trap a theme-switched hover text would hit
     against this unchanged, always-medium-dark hover fill. */
  --gt-state-warning-bg:     var(--gt-ref-state-warning-bg);
  --gt-seed-ok-border:       var(--gt-ref-seed-ok-border);
  --gt-btn-primary-fg:       var(--gt-ref-btn-solid-fg);
  --gt-btn-primary-hover-bg: var(--gt-ref-btn-primary-hover-bg);

  /* ── Deferred item 144 correction: .wo-issue-none's own text token
     (2026-07-17) ── previously reused --gt-result-item-not-checked-
     border (shared with the unrelated .results-item-not_checked
     border-left), whose Porcelain value was chosen for THAT selector's
     border-contrast need, not for text — only 2.31:1 as text against
     .wo-issue-none's own background. Split into its own token so the
     shared one stays untouched; Studio side reuses the SAME
     --gt-ref-studio-text-muted anchor .wo-issue-none already had, so
     Studio's computed value is UNCHANGED. */
  --gt-wo-issue-none-fg: var(--gt-ref-wo-issue-none-fg);
}

/* ── Theme: Light (receptionist / owner desktop — default) ──── */
/* Preserves current desktop layout; fine-tunes palette for premium clarity. */
.theme-light {
  /* "Porcelain" light desktop (ADR 0020 §5 D2) — formalizes the existing
     R2D tone verbatim: grounded cool premium-light, canvas deeper so cards
     pop, cool near-black text. Primary action = deep blue-teal
     (blue-dominant), NOT the vetoed bright admin-blue, NOT navy, NOT
     green-petrol. GT red stays brand/danger only. DS-1A: values unchanged,
     now sourced from tokens.css's reference layer. */
  --gt-bg:            var(--gt-ref-porcelain-bg);
  --gt-surface:       var(--gt-ref-porcelain-surface);
  --gt-surface-2:     var(--gt-ref-porcelain-surface-2);
  --gt-surface-muted: var(--gt-ref-porcelain-surface-muted);
  --gt-text:          var(--gt-ref-porcelain-text);
  --gt-text-muted:    var(--gt-ref-porcelain-text-muted);
  --gt-text-soft:     var(--gt-ref-porcelain-text-soft);
  --gt-accent:        var(--gt-ref-porcelain-accent);
  --gt-accent-hover:  var(--gt-ref-porcelain-accent-hover);
  --gt-accent-soft:   var(--gt-ref-porcelain-accent-soft);
  --gt-success:       var(--gt-ref-porcelain-success);
  --gt-success-bg:    var(--gt-ref-porcelain-success-bg);
  --gt-warning:       var(--gt-ref-porcelain-warning);
  --gt-warning-bg:    var(--gt-ref-porcelain-warning-bg);
  --gt-danger:        var(--gt-ref-porcelain-danger);
  --gt-danger-bg:     var(--gt-ref-porcelain-danger-bg);
  --gt-border:        var(--gt-ref-porcelain-border);
  /* PATH08-RECEPTION-OWNER-IMPLEMENTATION-FIDELITY-01 (2026-09-23), accepted 2026-09-19/20: the main button is the
     blue-teal #1F6F7E («оставляем как было»), and a field's or an outlined button's edge is #768089 (≥ 3.12:1) —
     #CBD2DC measured 1.2–1.5:1 and left fields and the rights switches nearly invisible. */
  --gt-solid-accent-bg:       var(--gt-ref-desk-main);
  --gt-solid-accent-bg-hover: var(--gt-ref-desk-main-hover);
  --gt-field-border:          var(--gt-ref-porcelain-field-border);
  /* A photo's frame is an edge like a field's (accepted 2026-09-20, ≥ 3.12:1 on every light background): #cccccc and
     the light --gt-border measured under it on the card and the results pages. */
  --gt-photo-thumb-border:    var(--gt-ref-porcelain-field-border);
  /* PATH08-REUSABLE-VISUAL-ACCEPTANCE-AND-UI-CLOSURE-01: both greys were bound once, in :root, to
     #6b7280 and no theme rebound them. Measured on the receptionist's results at 2560x1440: the
     «Начат · Принят · Выполнен · Пробег» line 3.75:1 on this page ground, «— Не проверено: 0»
     4.39:1 on its badge. Each desktop theme now reads them as its own muted text. */
  --gt-gray:          var(--gt-text-muted);
  --gt-result-skip-fg: var(--gt-text-muted);
  --gt-focus-ring:    rgba(27, 103, 117, 0.32);
  --gt-radius-sm:     10px;
  --gt-radius-md:     14px;
  --gt-radius-lg:     18px;
  --gt-radius-xl:     22px;
  --gt-shadow-sm:     0 6px 18px rgba(22, 31, 45, .10);
  --gt-shadow-md:     0 16px 40px rgba(22, 31, 45, .15);
}

/* ── Theme: "Studio+Command" dark desktop (ADR 0020 §5 D2) — NEW this
   stage (DS-1A). Switchable with .theme-light via the base.html toggle;
   architecturally distinct from the mechanic mobile theme below
   (.theme-dark / --mi-*), which is untouched by this stage. Values traced
   from the accepted system reference (ADR 0020 §5); the 3 states the
   reference did not enumerate explicitly (accent hover, a translucent
   focus ring, and a 3rd text-emphasis tier) are computed from those SAME
   accepted anchors via color-mix()/rgba() — flagged for owner refinement
   at DS-1 visual acceptance, not a fabricated new color. */
.theme-dark-desktop {
  --gt-bg:            var(--gt-ref-studio-bg);
  --gt-surface:       var(--gt-ref-studio-surface);
  --gt-surface-2:     var(--gt-ref-studio-surface-2);
  --gt-surface-muted: var(--gt-ref-studio-surface-muted);
  --gt-text:          var(--gt-ref-studio-text);
  --gt-text-muted:    var(--gt-ref-studio-text-muted);
  /* PATH08-REUSABLE-VISUAL-ACCEPTANCE-AND-UI-CLOSURE-01: :root binds this grey to #6b7280 —
     measured 3.73:1 on this page ground and 2.92:1 for a note on a fault card. */
  --gt-gray:          var(--gt-text-muted);
  /* Pending owner refinement at DS-1 acceptance — derived, not fabricated: */
  --gt-text-soft:     color-mix(in srgb, var(--gt-ref-studio-text-muted) 70%, var(--gt-ref-studio-surface-muted));
  --gt-accent:        var(--gt-ref-studio-accent);
  --gt-accent-hover:  color-mix(in srgb, var(--gt-ref-studio-accent) 85%, white);
  --gt-accent-soft:   var(--gt-ref-studio-accent-soft);
  --gt-success:       var(--gt-ref-studio-success);
  --gt-success-bg:    var(--gt-ref-studio-success-bg);
  --gt-warning:       var(--gt-ref-studio-warning);
  --gt-warning-bg:    var(--gt-ref-studio-warning-bg);
  --gt-danger:        var(--gt-ref-studio-danger);
  --gt-danger-bg:     var(--gt-ref-studio-danger-bg);
  --gt-border:        var(--gt-ref-studio-border);
  /* PATH08-RECEPTION-OWNER-IMPLEMENTATION-FIDELITY-01: the same blue-teal main button as the light desk. */
  --gt-solid-accent-bg:       var(--gt-ref-desk-main);
  --gt-solid-accent-bg-hover: var(--gt-ref-desk-main-hover);
  /* A var() in a custom property resolves where it is declared, so the field edge is re-declared per theme. */
  --gt-field-border:          var(--gt-ref-studio-border);
  --gt-focus-ring:    rgba(114, 183, 238, 0.35);
  --gt-radius-sm:     10px;
  --gt-radius-md:     14px;
  --gt-radius-lg:     18px;
  --gt-radius-xl:     22px;
  --gt-shadow-sm:     0 6px 18px rgba(0, 0, 0, .30);
  --gt-shadow-md:     0 16px 40px rgba(0, 0, 0, .45);

  /* ── DS-1B: shared component tokens, Studio+Command dark equivalents ──
     info has no dedicated --gt-ref-studio-* pair (it reuses the existing
     accent/accent-soft anchors, same pattern already used elsewhere in
     this file for accent-tinted badges/pills, e.g. .rc-chosen-badge/
     .rc-count/.rc-card-ic). success/warning/danger/badge/secondary-button
     reuse the already-accepted --gt-ref-studio-* anchors 1:1 — no new
     color is invented here. --gt-info-bg did not previously have a
     .theme-dark-desktop override at all (silently stayed the light-blue
     Porcelain tint even in dark mode) — this is the fix. */
  --gt-info-bg:                 var(--gt-ref-studio-accent-soft);
  --gt-state-info-fg:           var(--gt-ref-studio-accent);
  --gt-state-info-border:       var(--gt-ref-studio-accent);
  --gt-state-success-fg:        var(--gt-ref-studio-success);
  --gt-state-success-border:    var(--gt-ref-studio-success);
  --gt-state-danger-fg:         var(--gt-ref-studio-danger);
  --gt-state-danger-border:     var(--gt-ref-studio-danger);
  --gt-state-warning-fg:        var(--gt-ref-studio-warning);
  --gt-state-warning-border:    var(--gt-ref-studio-warning);

  --gt-btn-secondary-bg:        var(--gt-ref-studio-surface-2);
  --gt-btn-secondary-bg-hover:  color-mix(in srgb, var(--gt-ref-studio-surface-2) 80%, white);
  --gt-btn-secondary-fg:        var(--gt-ref-studio-text);

  --gt-badge-neutral-bg:        var(--gt-ref-studio-surface-2);

  /* DS-1D: table chrome reuses already-accepted Studio anchors — a
     readable elevated header/hover surface (surface-2, same tier as
     .btn-secondary/.badge above), muted header label text, and the
     ALREADY WCAG-verified (deferred item 129) non-text row-divider border. */
  --gt-table-header-bg:         var(--gt-ref-studio-surface-2);
  --gt-table-header-fg:         var(--gt-ref-studio-text-muted);
  --gt-table-row-border:        var(--gt-ref-studio-border);

  /* DS-1E: form-control focus reuses the SAME already-accepted Studio
     accent/focus-ring already used by .rc-input/.ro-search-input, so the
     global input/select/textarea focus state now matches those newer
     components instead of staying a flat, non-switched blue. */
  --gt-form-focus-border:       var(--gt-accent);
  --gt-form-focus-ring:         0 0 0 3px var(--gt-focus-ring);

  /* DS-1F: deferred item 132 resolver. Text/border/outline accents reuse the already-
     accepted Studio accent/focus-ring anchors (same pattern as DS-1E's
     form-focus tokens). --gt-solid-accent-bg/-hover are DELIBERATELY NOT
     overridden here — they stay theme-neutral (see the :root comment) to
     avoid a white-on-light-blue contrast regression. */
  --gt-interactive-accent:      var(--gt-accent);
  --gt-interactive-focus-ring:  0 0 0 3px var(--gt-focus-ring);
  --gt-btn-primary-focus-ring:  var(--gt-interactive-focus-ring);

  /* Deferred item 133 resolver: a lightened (not fabricated — same
     color-mix-toward-white pattern and 85/15 ratio already used by
     --gt-accent-hover above) derivation of the ALREADY WCAG-verified
     (deferred item 129) --gt-ref-studio-border, giving the hover state a
     genuinely brighter/more prominent border than the resting state —
     the same relationship Porcelain's own hover value (darker than its own
     resting border) has, just inverted for a dark canvas. */
  --gt-filter-hover-border:     color-mix(in srgb, var(--gt-ref-studio-border) 85%, white);

  /* .toast is DELIBERATELY NOT overridden here — theme-invariant by
     design (see the :root comment). .splus-status-badge states reuse the
     SAME already-accepted, already WCAG-verified Studio anchors DS-1B's
     own --gt-success-bg/--gt-warning-bg/--gt-danger-bg/--gt-state-
     warning-fg/--gt-state-danger-fg overrides use — no new dark color is
     fabricated. --gt-splus-badge-neutral-* reuses the exact same
     surface-2/text-muted pair already proven for DS-1D's table header. */
  --gt-splus-badge-neutral-bg:   var(--gt-ref-studio-surface-2);
  --gt-splus-badge-neutral-fg:   var(--gt-ref-studio-text-muted);
  --gt-splus-badge-ok-bg:        var(--gt-ref-studio-success-bg);
  --gt-splus-badge-warn-bg:      var(--gt-ref-studio-warning-bg);
  --gt-splus-badge-warn-fg:      var(--gt-ref-studio-warning);
  --gt-splus-badge-blocked-bg:   var(--gt-ref-studio-danger-bg);
  --gt-splus-badge-blocked-fg:   var(--gt-ref-studio-danger);

  /* T18-11E receptionist inspection-results: every state reuses an
     ALREADY-accepted Studio anchor except "not applicable" (purple),
     which has no existing Studio anchor anywhere — derived via
     color-mix() from this stage's own new --gt-ref-result-na-fg,
     matching the already-established derivation technique (--gt-accent-
     hover/--gt-filter-hover-border), not fabricated. Worst-case measured
     contrast for every one of these (see the focused checker) clears
     WCAG text (>=4.5:1) and non-text border (>=3:1) minimums. */
  --gt-result-neutral-bg:              var(--gt-ref-studio-surface-2);
  --gt-result-neutral-fg:              var(--gt-ref-studio-text-muted);
  --gt-result-ok-badge-bg:             var(--gt-ref-studio-success-bg);
  --gt-result-ok-fg:                   var(--gt-ref-studio-success);
  --gt-result-issue-badge-bg:          var(--gt-ref-studio-danger-bg);
  --gt-result-issue-fg:                var(--gt-ref-studio-danger);
  --gt-result-skip-fg:                 var(--gt-ref-studio-text-muted);
  --gt-result-skipped-badge-bg:        var(--gt-ref-studio-accent-soft);
  --gt-result-skipped-badge-fg:        var(--gt-ref-studio-accent);
  --gt-result-state-skipped-fg:        var(--gt-ref-studio-accent);
  --gt-result-na-badge-bg:             color-mix(in srgb, var(--gt-ref-result-na-fg) 20%, black);
  --gt-result-na-fg:                   color-mix(in srgb, var(--gt-ref-result-na-fg) 40%, white);
  --gt-result-item-ok-border:          var(--gt-ref-studio-success);
  --gt-result-item-issue-border:       var(--gt-ref-studio-danger);
  --gt-result-item-issue-bg:           var(--gt-ref-studio-danger-bg);
  --gt-result-item-not-checked-border: var(--gt-ref-studio-text-muted);
  --gt-result-item-skipped-border:     var(--gt-ref-studio-accent);
  --gt-result-item-skipped-bg:         var(--gt-ref-studio-accent-soft);
  --gt-result-item-na-border:          color-mix(in srgb, var(--gt-ref-result-na-fg) 40%, white);
  --gt-result-item-na-bg:              color-mix(in srgb, var(--gt-ref-result-na-fg) 20%, black);
  --gt-photo-thumb-border:             var(--gt-ref-studio-border);
  --gt-result-all-clear-bg:            var(--gt-ref-studio-success-bg);
  --gt-result-all-clear-fg:            var(--gt-ref-studio-success);

  /* ── DS-1 package 1: reception list/detail/results (2026-07-17) ──────
     Draft/cancelled/annulled/paused are all non-actionable "inactive/
     administrative" states — collapsed to ONE consistent muted Studio
     treatment (--gt-ref-studio-text-muted / --gt-ref-studio-surface-2,
     the SAME already-accepted anchor pair DS-1B's neutral badge and the
     .splus-status-badge neutral state already use) rather than
     fabricating 3 distinct new dark hues for non-urgent states.
     --gt-results-widget-issue-bg reuses --gt-ref-studio-danger-bg, the
     SAME anchor already verified for the reception-results issue card
     (T18-11E) — same "issue" semantic, different screen's historical
     Porcelain hex. --gt-accent-solid-fg/--gt-danger-solid-fg DO switch
     here (see the correction note in :root above) — Studio's --gt-accent/
     --gt-danger are light colors, so the text sitting on their flat
     fills (.ro-filter.is-active/.ro-filter-decide.is-active/.ro-cal-
     day.is-edge) needs a DARK color here, reusing the already-accepted
     --gt-ref-studio-bg anchor (no new dark color fabricated) rather than
     the near-white that's correct only in Porcelain. --gt-cta-gradient-
     top(-hover)/--gt-cta-solid-fg/--gt-lightbox-text are intentionally
     NOT overridden here — see their theme-neutral rationale in :root
     above. */
  --gt-accent-solid-fg:         var(--gt-ref-studio-bg);
  --gt-danger-solid-fg:         var(--gt-ref-studio-bg);
  --gt-status-draft-chip-bg:    var(--gt-ref-studio-surface-2);
  --gt-status-draft-chip-fg:    var(--gt-ref-studio-text-muted);
  --gt-status-draft-accent:     var(--gt-ref-studio-text-muted);
  --gt-status-cancelled-accent: var(--gt-ref-studio-text-muted);
  --gt-status-annulled-accent:  var(--gt-ref-studio-text-muted);
  --gt-status-admin-chip-bg:    var(--gt-ref-studio-surface-2);
  --gt-status-admin-chip-fg:    var(--gt-ref-studio-text-muted);
  --gt-results-widget-issue-bg: var(--gt-ref-studio-danger-bg);

  /* ── DS-1 package 2: shared desktop status/notice/intake/primary-
     action primitives (2026-07-17) ──────────────────────────────────
     --gt-state-warning-bg/--gt-seed-ok-border reuse ALREADY-accepted
     Studio anchors (studio-warning-bg matches --gt-state-warning-fg's
     own existing studio-warning mapping; studio-success matches
     --gt-state-success-border/--gt-result-item-ok-border's own existing
     mapping) — no new dark color fabricated. --gt-btn-primary-fg
     switches to the already-accepted --gt-ref-studio-bg anchor (same
     dark-text-on-light-fill pattern as package 1's --gt-accent-solid-fg/
     --gt-danger-solid-fg), since Studio's --gt-accent is a light color
     and this token's ONLY consumer is .btn-primary's own text.
     --gt-btn-primary-hover-bg is intentionally NOT overridden here —
     see the theme-neutral rationale in :root above. */
  --gt-state-warning-bg: var(--gt-ref-studio-warning-bg);
  --gt-seed-ok-border:   var(--gt-ref-studio-success);
  --gt-btn-primary-fg:   var(--gt-ref-studio-bg);

  /* Deferred item 144 correction: --gt-wo-issue-none-fg reuses the SAME
     --gt-ref-studio-text-muted anchor --gt-result-item-not-checked-
     border already used here — Studio's computed value for
     .wo-issue-none is UNCHANGED by this correction. */
  --gt-wo-issue-none-fg: var(--gt-ref-studio-text-muted);
}

/* ── Theme: Dark (mechanic mobile — opt-in, not applied globally yet) ─── */
/* Applied per-template in T18-17D. Defined here as foundation infrastructure. */
.theme-dark {
  --gt-bg:            #0B1220;
  --gt-surface:       #131C2D;
  --gt-surface-2:     #1B263B;
  --gt-surface-muted: #101827;
  --gt-text:          #F8FAFC;
  --gt-text-muted:    #CBD5E1;
  --gt-text-soft:     #94A3B8;
  --gt-accent:        #3B82F6;
  --gt-accent-hover:  #60A5FA;
  --gt-accent-soft:   rgba(59,130,246,.16);
  --gt-success:       #22C55E;
  --gt-success-bg:    rgba(34,197,94,.14);
  --gt-warning:       #F59E0B;
  --gt-warning-bg:    rgba(245,158,11,.14);
  --gt-danger:        #EF4444;
  --gt-danger-bg:     rgba(239,68,68,.14);
  --gt-border:        #263247;
  --gt-focus-ring:    rgba(96,165,250,.32);
  --gt-radius-sm:     10px;
  --gt-radius-md:     14px;
  --gt-radius-lg:     18px;
  --gt-radius-xl:     22px;
  --gt-shadow-sm:     0 8px 20px rgba(0,0,0,.30);
  --gt-shadow-md:     0 18px 45px rgba(0,0,0,.50);
}

/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-FIDELITY-01 (2026-09-23): the desk's blue-teal main button and field edge are
   not the mechanic's. The mechanic scope sits inside a body that carries a desk theme class, so it keeps the
   values it had, explicitly, in a rule of its own — the .theme-dark block itself is left byte for byte. */
.mech-app.theme-dark { --gt-solid-accent-bg: var(--gt-primary); --gt-solid-accent-bg-hover: var(--gt-primary-hover); --gt-field-border: var(--gt-border); }

/* ── Reset ───────────────────────────────────────────────── */
* {
  box-sizing: border-box;
}

/* ── Base ────────────────────────────────────────────────── */
body {
  margin: 0;
  /* R2C: use the already-loaded Inter web font (see @font-face at top) — the
     app previously shipped Inter but rendered the body in Arial. System
     fallbacks preserved; no external font loading. */
  font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  background: var(--gt-bg);
  color: var(--gt-text);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3 {
  margin-top: 0;
}

/* ── Links — modern enterprise default ───────────────────── */
a {
  color: var(--gt-interactive-accent);
  text-decoration: none;
}

a:hover,
a:focus-visible {
  text-decoration: underline;
}

/* Button-like and pill links never underline */
.btn:hover,
.btn:focus-visible,
.nav a:hover,
.nav a:focus-visible,
.filters a:hover,
.filters a:focus-visible,
.tab:hover,
.quick-btn:hover {
  text-decoration: none;
}

/* R5: card/button/pill-style R-series links never underline on hover/focus —
   hover affordance comes from background/border/box-shadow instead (see each
   component's own :hover rule). This closes the systemic underline-noise gap:
   these classes were only set to text-decoration:none in their base state,
   which the global a:hover rule above (same specificity, declared later)
   was overriding on hover. */
.ro-row:hover,
.ro-row:focus-visible,
.ro-filter:hover,
.ro-filter:focus-visible,
.rc-btn:hover,
.rc-btn:focus-visible,
.rc-change:hover,
.rc-change:focus-visible,
.rc-pick-live-link:hover,
.rc-pick-live-link:focus-visible,
.rw-photo-link:hover,
.rw-photo-link:focus-visible,
.ro-pager-btn:hover,
.ro-pager-btn:focus-visible,
.ro-period:hover,
.ro-period:focus-visible,
.ro-search-clear:hover,
.ro-search-clear:focus-visible {
  /* R6P-2: same systemic underline-noise fix as R5 (see comment above) — these
     4 classes were missed the first time; caught by the owner as "ugly
     underlined link styling" on the pager/date-filter chips/search-clear. */
  text-decoration: none;
}

h1 {
  font-size: 26px;
}

/* ── Layout ──────────────────────────────────────────────── */
/* Owner report (2026-07-22): staff monitors are 2K+ and the fixed
   max-width caps left a lot of dead space unused. min(96vw, <cap>)
   scales automatically with the real viewport instead of jumping to one
   fixed number — narrower screens are completely unaffected (96vw is
   already smaller than the cap there, same behavior as before), wide
   monitors get real extra width up to a still-readable ceiling. */
.container {
  max-width: min(96vw, 1440px);
  margin: 0 auto;
  padding: 24px 28px;
}

/* ── Header / Nav — dark slate app shell ─────────────────────────────────
   DS-1 Gate 1 (2026-07-17): reskinned to the accepted system reference's
   product-bar pattern (taller bar, tab-underline nav instead of a pill
   background) — CSS only, .header/.brand/.nav markup in base.html is
   unchanged, so every href/label/conditional is preserved exactly. */
.header {
  background: var(--gt-shell-bg);
  color: var(--gt-shell-text);
  border-bottom: 1px solid var(--gt-shell-border);
  min-height: 56px;
  padding: 0 28px;
  display: flex;
  align-items: center;
  gap: 32px;
  flex-wrap: wrap;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  white-space: nowrap;
}

.brand-logo {
  height: 32px;
  width: auto;
  display: block;
}

.brand-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--gt-shell-label-fg);
  border: 1px solid var(--gt-shell-label-border);
  border-radius: 6px;
  padding: 2px 7px;
}

.nav {
  align-self: stretch;
  margin-top: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px;
}

/* DS-1 Gate 1: product-bar tab pattern — border-bottom indicator, full-height
   hit target, instead of the earlier pill background. */
.nav a {
  display: inline-flex;
  align-items: center;
  align-self: stretch;
  color: var(--gt-shell-nav-fg);
  text-decoration: none;
  margin-right: 2px;
  font-weight: 600;
  font-size: 13.5px;
  padding: 0 14px;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  transition: color .15s, border-color .15s, background .15s;
}

.nav a:hover {
  color: var(--gt-shell-nav-fg-hover);
  background: var(--gt-shell-nav-bg-hover);
}

.nav a.active {
  color: var(--gt-shell-nav-fg-hover);
  border-bottom-color: var(--gt-shell-nav-fg-hover);
}

.nav a:focus-visible {
  outline: none;
  box-shadow: var(--gt-focus);
  border-radius: var(--gt-radius-sm);
}

/* REMOVED 2026-07-22 (owner-reported: toggle not centered in the rail): this
   rule dated from the OLD DS-1A header-based toggle placement ("push right
   in the horizontal .header row via margin-left:auto" + "never wrap the
   text caption that used to sit next to it"). The toggle has lived in the
   vertical .gt-rail-bottom column since the desktop-rail redesign (2026-07-21)
   and no longer has a text caption — `.gt-theme-toggle` is the ONLY selector
   match in the whole template tree (verified), so this rule had no remaining
   legitimate purpose. In `.gt-rail-bottom`'s flex-column layout, an
   asymmetric `margin-left: auto` cross-axis margin absorbed ALL free space
   on the left, pushing the 56px-wide pill flush against the column's right
   edge instead of letting `.gt-rail-bottom`'s own `align-items: center`
   center it — exactly the reported misalignment. Removed entirely; the
   toggle now centers like every other `.gt-rail-link` in the column. */

/* ── Card ────────────────────────────────────────────────── */
.card {
  background: var(--gt-surface);
  border: 1px solid var(--gt-border);
  border-radius: var(--gt-radius-lg);
  padding: 22px;
  margin-bottom: 18px;
  box-shadow: var(--gt-shadow-sm);
  transition: box-shadow .15s, border-color .15s;
}

.card:hover {
  box-shadow: var(--gt-shadow-md);
}

/* ── KPI grid ────────────────────────────────────────────── */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}

/* #131 fix (2026-07-15): background/color/border-left/label used to be
   hardcoded (--gt-graphite/white/--gt-red/#c8cdd5) — a fixed near-black
   card with a GT-red stripe regardless of theme. In Porcelain (light) this
   read as a mismatched black box on an otherwise light page; --gt-red is
   also the documented brand/logo-only accent, never a UI color (see
   style.css's own "--gt-red: ... legacy alias — do NOT use as primary UI
   color" note). Now sourced from the SAME existing, already
   theme-switched semantic tokens every other card/surface on the page
   uses — zero new tokens needed. */
.kpi {
  background: var(--gt-surface-2);
  color: var(--gt-text);
  padding: 16px 18px;
  border-radius: var(--gt-radius-lg);
  border-left: 5px solid var(--gt-accent);
}

.kpi .value {
  font-size: 26px;
  font-weight: 800;
}

.kpi .label {
  font-size: 12px;
  color: var(--gt-text-muted);
  margin-top: 5px;
}

/* ── Table ───────────────────────────────────────────────── */
table {
  width: 100%;
  border-collapse: collapse;
  background: var(--gt-surface);
}

th {
  background: var(--gt-table-header-bg);
  color: var(--gt-table-header-fg);
  text-align: left;
  padding: 10px 12px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--gt-border);
}

th:first-child { border-radius: var(--gt-radius-sm) 0 0 0; }
th:last-child  { border-radius: 0 var(--gt-radius-sm) 0 0; }

td {
  border-bottom: 1px solid var(--gt-table-row-border);
  padding: 9px 12px;
  vertical-align: top;
  font-size: 13.5px;
}

tr:hover td {
  background: var(--gt-table-header-bg);
}

/* ── Forms ───────────────────────────────────────────────── */
input, select, textarea {
  width: 100%;
  padding: 9px 10px;
  border: 1px solid var(--gt-field-border);
  border-radius: var(--gt-radius);
  font-family: inherit;
  font-size: 14px;
  background: var(--gt-surface);
  color: var(--gt-text);
  transition: border-color .15s, box-shadow .15s;
}

input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--gt-form-focus-border);
  box-shadow: var(--gt-form-focus-ring);
}

input[type="checkbox"]:focus,
input[type="radio"]:focus {
  outline: none;
  box-shadow: none;
}

input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
  outline: 2px solid var(--gt-interactive-accent);
  outline-offset: 2px;
}

/* ── Shared caret for ordinary single-select controls ──────────────────
   Template-list correction (2026-07-21): one consistent custom chevron for
   every plain <select> across the app, replacing inconsistent native chrome
   (some pages drew the OS caret, the reception command bar drew a custom
   one). Element-level specificity (0,0,1) on purpose: any specialized
   select COMPONENT class (e.g. .rc-select, 0,1,0) still wins and keeps its
   own caret. Multiple/size list pickers keep native chrome. The chevron is
   the same slate glyph .rc-select already uses, so the treatment is
   genuinely one shared caret, with a balanced right inset. */
select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding-right: 2.2rem; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748B' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 0.85rem center; background-size: 1.05rem;
}
select[multiple], select[size] {
  appearance: auto; -webkit-appearance: auto; -moz-appearance: auto;
  padding-right: 10px; cursor: auto; background-image: none;
}
select::-ms-expand { display: none; }

/* ── Controlled enterprise checkbox (.item-check) ────────── */
input[type="checkbox"].item-check {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  border: 1.5px solid var(--gt-border);
  border-radius: 5px;
  background: var(--gt-surface);
  box-shadow: none;
  cursor: pointer;
  vertical-align: middle;
  position: relative;
  flex-shrink: 0;
  transition: background .12s, border-color .12s;
}

input[type="checkbox"].item-check:checked {
  background: var(--gt-solid-accent-bg);
  border-color: var(--gt-solid-accent-bg);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpolyline points='2%2C6 5%2C9 10%2C3' fill='none' stroke='%23ffffff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 10px 10px;
}

input[type="checkbox"].item-check:focus {
  outline: none;
  box-shadow: none;
}

input[type="checkbox"].item-check:focus-visible {
  outline: 2px solid var(--gt-interactive-accent);
  outline-offset: 2px;
  box-shadow: none;
}

input[type="checkbox"].item-check:disabled {
  opacity: .45;
  cursor: not-allowed;
  background: var(--gt-surface-muted);
  border-color: var(--gt-border);
}

textarea {
  min-height: 110px;
  resize: vertical;
}

.form-row {
  margin-bottom: 14px;
}

/* ── Buttons ─────────────────────────────────────────────── */
.btn {
  display: inline-block;
  border: none;
  background: var(--gt-solid-accent-bg);
  color: white;
  padding: 9px 16px;
  border-radius: var(--gt-radius);
  font-weight: 700;
  font-size: 13.5px;
  text-decoration: none;
  cursor: pointer;
  transition: background .15s, box-shadow .15s, transform .1s;
  white-space: nowrap;
}

.btn:hover {
  background: var(--gt-solid-accent-bg-hover);
}

.btn:active {
  transform: translateY(1px);
}

/* Submit-in-progress visual state (set by generic form JS) */
.btn.is-submitting,
.is-submitting {
  opacity: .7;
  cursor: progress;
  pointer-events: none;
}

.btn:focus-visible {
  outline: none;
  box-shadow: var(--gt-interactive-focus-ring);
}

.btn:disabled,
.btn-disabled {
  opacity: .45;
  cursor: not-allowed;
  pointer-events: none;
}

/* Secondary — neutral dark */
.btn-secondary {
  background: var(--gt-btn-secondary-bg);
  color: var(--gt-btn-secondary-fg);
  border: 1px solid var(--gt-border);
}

.btn-secondary:hover {
  background: var(--gt-btn-secondary-bg-hover);
}

/* Primary alias — blue, does NOT override .btn globally */
.btn.primary,
.btn-primary {
  background: var(--gt-solid-accent-bg);
  color: white;
  border: none;
}

.btn.primary:hover,
.btn-primary:hover {
  background: var(--gt-solid-accent-bg-hover);
}

.btn.primary:focus-visible,
.btn-primary:focus-visible {
  outline: none;
  box-shadow: var(--gt-btn-primary-focus-ring);
}

/* Success — professional green */
.btn-success {
  background: var(--gt-green);
  color: var(--gt-btn-solid-fg);
  border: none;
}

.btn-success:hover {
  background: var(--gt-btn-success-bg-hover);
}

.btn-success:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--gt-btn-success-focus-ring);
}

/* Danger */
.btn-danger {
  background: var(--gt-btn-danger-bg);
  color: var(--gt-btn-solid-fg);
  border: none;
}

.btn-danger:hover {
  background: var(--gt-btn-danger-bg-hover);
}

.btn-danger:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--gt-btn-danger-focus-ring);
}

/* Quick action pills (recommendation_item_detail) */
.quick-btn {
  border: 1px solid var(--gt-border);
  border-radius: 999px;
  background: var(--gt-surface);
  color: var(--gt-text);
  padding: 7px 13px;
  font-weight: 700;
  font-size: 13px;
  cursor: pointer;
  transition: background .15s;
}

.quick-btn:hover {
  background: var(--gt-surface-muted);
}

.quick-btn:focus-visible {
  outline: none;
  box-shadow: var(--gt-interactive-focus-ring);
}

.quick-btn.active {
  background: var(--gt-solid-accent-bg);
  border-color: var(--gt-solid-accent-bg);
  color: white;
}

/* ── Filter / tab pills ──────────────────────────────────── */
.filters a {
  display: inline-block;
  margin: 0 6px 8px 0;
  padding: 6px 12px;
  background: var(--gt-surface);
  border: 1px solid var(--gt-border);
  border-radius: 999px;
  text-decoration: none;
  color: var(--gt-text);
  font-size: 13px;
  font-weight: 600;
  transition: background .15s, border-color .15s;
}

.filters a:hover {
  background: var(--gt-surface-muted);
  border-color: var(--gt-filter-hover-border);
}

.filters a.active {
  background: var(--gt-solid-accent-bg);
  color: white;
  border-color: var(--gt-solid-accent-bg);
}

.filters a:focus-visible {
  outline: none;
  box-shadow: var(--gt-interactive-focus-ring);
}

/* ── Badge / status labels ───────────────────────────────── */
.badge {
  display: inline-block;
  padding: 3px 9px;
  background: var(--gt-badge-neutral-bg);
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .01em;
}

.badge-red {
  background: var(--gt-danger-bg);
  color: var(--gt-state-danger-fg);
}

.badge-blue {
  background: var(--gt-info-bg);
  color: var(--gt-state-info-fg);
}

/* ── Alert / notice blocks ───────────────────────────────── */

/* Base notice (info) */
.notice {
  border-radius: var(--gt-radius-lg);
  padding: 12px 16px;
  margin-bottom: 12px;
  font-weight: 700;
  font-size: 13.5px;
  background: var(--gt-info-bg);
  border: 1px solid var(--gt-state-info-border);
  color: var(--gt-state-info-fg);
}

.notice.good {
  background: var(--gt-success-bg);
  border-color: var(--gt-state-success-border);
  color: var(--gt-state-success-fg);
}

.notice.neutral {
  background: var(--gt-info-bg);
  border-color: var(--gt-state-info-border);
  color: var(--gt-state-info-fg);
}

.notice.danger {
  background: var(--gt-danger-bg);
  border-color: var(--gt-state-danger-border);
  color: var(--gt-state-danger-fg);
}

/* Success alert — .alert-success (used in recommendation_groups.html) */
.alert-success {
  background: var(--gt-success-bg);
  border: 1px solid var(--gt-state-success-border);
  color: var(--gt-state-success-fg);
  border-radius: var(--gt-radius-lg);
  padding: 12px 16px;
  font-weight: 700;
  font-size: 13.5px;
}

/* .callout — informational block (used in recommendation_audit.html) */
.callout {
  background: var(--gt-info-bg);
  border: 1px solid var(--gt-state-info-border);
  border-radius: var(--gt-radius-lg);
  padding: 14px 16px;
  color: var(--gt-state-info-fg);
  font-size: 13.5px;
}

/* .ok — success inline result (used in recommendation_audit.html after apply) */
.ok {
  background: var(--gt-success-bg);
  border: 1px solid var(--gt-state-success-border);
  border-radius: var(--gt-radius-lg);
  padding: 12px 16px;
  color: var(--gt-state-success-fg);
  font-weight: 700;
  font-size: 13.5px;
}

/* .warning — warning block (used in completion-audit inline) */
.warning {
  background: var(--gt-warning-bg);
  border: 1px solid var(--gt-state-warning-border);
  border-radius: var(--gt-radius-lg);
  padding: 12px 16px;
  color: var(--gt-state-warning-fg);
  font-size: 13.5px;
}

/* ── Toolbar ─────────────────────────────────────────────── */
.toolbar {
  display: grid;
  grid-template-columns: 1.6fr 1fr 0.8fr auto;
  gap: 12px;
  align-items: end;
}

.toolbar label {
  display: block;
  font-size: 12px;
  font-weight: 700;
  color: var(--gt-muted);
  margin-bottom: 5px;
  text-transform: uppercase;
  letter-spacing: .04em;
}

.toolbar-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  padding-bottom: 0;
}

/* ── Info box (item detail header cells) ─────────────────── */
.item-header-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
  margin-top: 18px;
}

.info-box {
  background: var(--gt-surface-muted);
  border: 1px solid var(--gt-border);
  border-radius: var(--gt-radius-lg);
  padding: 14px;
}

.info-box strong {
  display: block;
  font-size: 17px;
  margin-top: 4px;
}

/* ── Action card accent ──────────────────────────────────── */
.action-card {
  border-left: 5px solid var(--gt-interactive-accent);
}

/* ── Quick-actions row ───────────────────────────────────── */
.quick-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.quick-actions form {
  margin: 0;
}

/* ── Form grids ──────────────────────────────────────────── */
.form-grid-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
}

.form-grid-4 {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}

/* ── Inline form ─────────────────────────────────────────── */
.inline-form {
  display: grid;
  grid-template-columns: 220px 260px 1fr auto;
  gap: 10px;
  align-items: center;
}

/* ── Section head ────────────────────────────────────────── */
.section-head {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  justify-content: space-between;
}

/* ── Pre / raw text ──────────────────────────────────────── */
pre {
  white-space: pre-wrap;
  background: var(--gt-surface-muted);
  border: 1px solid var(--gt-border);
  padding: 14px;
  border-radius: var(--gt-radius);
  font-size: 13px;
  line-height: 1.5;
}

/* ── Utility ─────────────────────────────────────────────── */
.small {
  color: var(--gt-muted);
  font-size: 12.5px;
}

.muted {
  color: var(--gt-muted);
  font-size: 13.5px;
}

.mb  { margin-bottom: 20px; }
.mt  { margin-top: 8px; }

details summary {
  cursor: pointer;
  color: var(--gt-muted);
  font-weight: 700;
}

/* ── Toast (non-blocking notification) ───────────────────── */
.toast {
  position: fixed;
  right: 24px;
  bottom: 24px;
  background: var(--gt-toast-bg);
  color: var(--gt-toast-fg);
  padding: 10px 18px;
  border-radius: var(--gt-radius);
  font-size: 13.5px;
  font-weight: 700;
  box-shadow: var(--gt-shadow-md);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .2s, transform .2s;
  pointer-events: none;
  z-index: 1000;
}

.toast.show {
  opacity: 1;
  transform: translateY(0);
}

/* ── Responsive ──────────────────────────────────────────── */
@media (max-width: 900px) {
  .section-head,
  .inline-form {
    display: block;
  }

  .toolbar,
  .item-header-grid,
  .form-grid-3,
  .form-grid-4 {
    grid-template-columns: 1fr;
  }

  .toolbar-actions {
    display: block;
  }

  .toolbar-actions .btn {
    margin-bottom: 8px;
  }

  .kpi-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ── Splus status badge ──────────────────────────────────── */
.splus-status-badge {
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  border-radius: 8px;
  padding: 4px 8px;
  margin-top: 4px;
  background: var(--gt-splus-badge-neutral-bg);
  color: var(--gt-splus-badge-neutral-fg);
}
.splus-status-badge:empty { display: none; }
.splus-status-badge.ok { background: var(--gt-splus-badge-ok-bg); color: var(--gt-state-success-fg); }
.splus-status-badge.warn { background: var(--gt-splus-badge-warn-bg); color: var(--gt-splus-badge-warn-fg); }
.splus-status-badge.blocked { background: var(--gt-splus-badge-blocked-bg); color: var(--gt-splus-badge-blocked-fg); }


/* ── T18-11C Slice A: Mechanic queue mobile-friendly styles ── */
.mechanic-name-form { max-width: 400px; margin: 2rem auto; }
.mechanic-name-input { width: 100%; font-size: 1.2rem; padding: 0.5rem 0.75rem; border: 1px solid var(--gt-border); border-radius: 6px; }
.btn-large { font-size: 1.05rem; padding: 0.7rem 1.5rem; min-width: 160px; }
.mechanic-task-list { display: flex; flex-direction: column; gap: 1rem; max-width: 620px; margin-top: 1rem; }
.mechanic-task-card { border: 1px solid var(--gt-border); border-radius: 8px; padding: 1rem 1.25rem; background: var(--gt-surface); }
.task-header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 0.4rem; }
.task-wo { font-size: 1.1rem; font-weight: 700; color: var(--gt-text); }
.task-template { font-size: 0.9rem; color: var(--gt-gray); }
.task-assigned { font-size: 0.9rem; color: var(--gt-gray); margin-bottom: 0.5rem; }
.task-pool { font-size: 0.9rem; color: var(--gt-gray); margin-bottom: 0.5rem; font-style: italic; }
.btn-take { width: 100%; margin-top: 0.4rem; }

/* ── T18-11D Slice B: Mechanic inspection execution styles ── */
.insp-header { margin-bottom: 1rem; }
.insp-status-badge { display: inline-block; padding: 3px 10px; border-radius: 12px; font-size: 0.85rem; font-weight: 600; }
/* DS-1 package 2 resolver (2026-07-17): .insp-status-draft/-in_progress
   tokenized, reusing the already-accepted T18-11E "result state" family
   (--gt-result-neutral-bg/-fg exact-match .insp-status-draft's raw
   pair; --gt-state-warning-fg exact-match .insp-status-in_progress's
   text — only its background was genuinely new). See tokens.css's own
   stage comment for the full trace. */
.insp-status-draft { background: var(--gt-result-neutral-bg); color: var(--gt-result-neutral-fg); }
.insp-status-in_progress { background: var(--gt-state-warning-bg); color: var(--gt-state-warning-fg); }
/* Deferred #136 resolver (2026-07-17, cautious/narrow scope — .insp-
   status-draft/-in_progress deliberately left untouched, not part of
   this stage): traced first — this exact raw pair (#ecfdf5/#065f46)
   byte-matches the ALREADY-accepted --gt-result-all-clear-bg/-fg
   (T18-11E), reused directly, no new token. Mechanic surfaces
   (.theme-dark/.mech-app) declare no override for this token pair, so
   they keep resolving to :root's Porcelain value — byte-identical to
   the old raw literal, zero visual/behavioral change on any mechanic
   screen. Desktop Studio+Command now switches to the already-accepted
   --gt-ref-studio-success-bg/-success anchor instead of staying stuck
   on the light-green literal. */
.insp-status-completed { background: var(--gt-result-all-clear-bg); color: var(--gt-result-all-clear-fg); }
/* PATH08-RECEPTION-UI-COHERENCE-01: the results screen used to print the raw
   database value for an unrecognised status; it now prints a readable name and
   needs a chip for it. Same warning pair as the other two surfaces. */
.insp-status-unknown { background: var(--gt-state-warning-bg); color: var(--gt-state-warning-fg); }
/* T18-68B: issue-count badge in the work-order inspection table — same
   found/clear/none vocabulary as .insp-status-* above, kept as its own class
   so it reads as a distinct column, not a status restatement. */
.wo-issue-badge { display: inline-block; padding: 3px 10px; border-radius: 12px; font-size: 0.85rem; font-weight: 600; }
/* DS-1 package 2 resolver (2026-07-17): .wo-issue-found/-none
   tokenized, reusing the already-accepted T18-11E "result state" family
   directly — both raw pairs byte-match existing semantic tokens
   exactly (--gt-result-issue-badge-bg/-fg for -found;
   --gt-result-neutral-bg/--gt-result-item-not-checked-border for
   -none), no new token needed. See tokens.css's own stage comment.
   Deferred item 144 correction (2026-07-17): .wo-issue-none's text
   corrected to its own --gt-wo-issue-none-fg — the shared
   --gt-result-item-not-checked-border it borrowed had a Porcelain value
   chosen for a DIFFERENT selector's (.results-item-not_checked) border
   contrast need, not text (only 2.31:1 as text; needed 4.5:1). Studio's
   computed value is unchanged (same --gt-ref-studio-text-muted anchor). */
.wo-issue-found { background: var(--gt-result-issue-badge-bg); color: var(--gt-result-issue-fg); }
.wo-issue-clear { background: var(--gt-result-all-clear-bg); color: var(--gt-result-all-clear-fg); }
.wo-issue-none { background: var(--gt-result-neutral-bg); color: var(--gt-wo-issue-none-fg); }
.insp-done-banner { background: var(--gt-result-all-clear-bg); color: var(--gt-result-all-clear-fg); padding: 0.75rem 1rem; border-radius: 8px; font-weight: 600; margin-bottom: 1rem; }
.back-link { font-size: 0.9rem; color: var(--gt-gray); text-decoration: none; }
.check-section { margin-bottom: 1.5rem; }
.check-section-title { font-weight: 700; font-size: 1rem; padding: 0.4rem 0; border-bottom: 1px solid var(--gt-border); margin-bottom: 0.75rem; }
.check-item { border: 1px solid var(--gt-border); border-radius: 8px; padding: 0.9rem 1rem; margin-bottom: 0.75rem; background: var(--gt-surface); }
.check-item-ok { border-left: 4px solid #16a34a; }
.check-item-issue { border-left: 4px solid #dc2626; }
.check-item-not_checked { border-left: 4px solid #9ca3af; }
.check-label { font-weight: 600; font-size: 1rem; margin-bottom: 0.5rem; }
.check-note { width: 100%; font-size: 0.95rem; padding: 0.4rem; border: 1px solid var(--gt-border); border-radius: 6px; resize: vertical; margin-bottom: 0.5rem; box-sizing: border-box; }
.state-btns { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.btn-state { flex: 1; min-width: 90px; padding: 0.6rem 0.4rem; font-size: 0.9rem; background: var(--gt-surface-muted); border: 1px solid var(--gt-border); border-radius: 6px; cursor: pointer; color: #374151; }
.btn-state-active-ok { background: #dcfce7; border-color: #16a34a; color: #15803d; font-weight: 700; }
.btn-state-active-issue { background: #fee2e2; border-color: #dc2626; color: #b91c1c; font-weight: 700; }
.btn-state-active-skip { background: #f3f4f6; border-color: #6b7280; color: #374151; font-weight: 700; }
.check-state-badge { font-size: 0.85rem; font-weight: 600; margin-bottom: 0.25rem; }
.state-ok { color: var(--gt-result-ok-fg); }
.state-issue { color: var(--gt-result-issue-fg); }
.state-not_checked { color: var(--gt-result-skip-fg); }
/* T18-33J: auto-skipped — calm info blue; not red/green */
.state-skipped_by_logic { color: var(--gt-result-state-skipped-fg); }
/* T18-66D: intentional Н/П — matches .results-item-not_applicable/.count-na violet */
.state-not_applicable { color: var(--gt-result-na-fg); }
.check-note-display { font-size: 0.9rem; color: var(--gt-gray); font-style: italic; margin-top: 0.25rem; }
.insp-complete-section { margin-top: 2rem; padding-top: 1rem; border-top: 1px solid var(--gt-border); }
.btn-complete { background: #1d4ed8; color: #fff; border: none; width: 100%; max-width: 400px; }
.btn-open { display: inline-block; text-align: center; text-decoration: none; background: #1d4ed8; color: #fff; border: none; width: 100%; margin-top: 0.5rem; }
.mechanic-task-inprogress { border-left: 4px solid #f59e0b; }
/* R6U: paused sub-state accent — still in_progress, so it keeps the amber
   left-border above; this just adds a quiet visual cue it's paused right now. */
.mechanic-task-paused { opacity: .85; }
.task-paused-badge { font-size: 0.9rem; font-weight: 600; color: #8B7FC0; margin-bottom: 0.5rem; }

/* ── T18-11E Slice C1: Receptionist results screen styles ── */
.results-header { margin-bottom: 0.75rem; }
.results-meta { font-size: 0.9rem; color: var(--gt-gray); margin-bottom: 0.75rem; }
.results-counts { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1rem; }
.count-badge { display: inline-block; padding: 4px 12px; border-radius: 12px; font-size: 0.85rem; font-weight: 600; }
.count-total { background: var(--gt-result-neutral-bg); color: var(--gt-result-neutral-fg); }
.count-ok { background: var(--gt-result-ok-badge-bg); color: var(--gt-result-ok-fg); }
.count-issue { background: var(--gt-result-issue-badge-bg); color: var(--gt-result-issue-fg); }
.count-skip { background: var(--gt-result-neutral-bg); color: var(--gt-result-skip-fg); }
.count-skipped { background: var(--gt-result-skipped-badge-bg); color: var(--gt-result-skipped-badge-fg); }
/* T18-66D: Н/П (not_applicable) is an intentional mechanic answer, distinct
   from "не проверено" (forgotten) — was sharing .count-skip's gray, making
   the two indistinguishable at a glance. */
.count-na { background: var(--gt-result-na-badge-bg); color: var(--gt-result-na-fg); }
.results-section { margin-bottom: 1.25rem; }
.results-section-title { font-weight: 700; font-size: 1rem; padding: 0.35rem 0; border-bottom: 1px solid var(--gt-border); margin-bottom: 0.5rem; }
.results-item { border: 1px solid var(--gt-border); border-radius: 6px; padding: 0.6rem 0.9rem; margin-bottom: 0.4rem; }
.results-item-ok { border-left: 4px solid var(--gt-result-item-ok-border); }
.results-item-issue { border-left: 4px solid var(--gt-result-item-issue-border); background: var(--gt-result-item-issue-bg); }
.results-item-not_checked { border-left: 4px solid var(--gt-result-item-not-checked-border); }
.results-item-skipped_by_logic { border-left: 4px solid var(--gt-result-item-skipped-border); background: var(--gt-result-item-skipped-bg); }
/* T18-66D: same rationale as .count-na — a distinct border/bg so a staff
   member scanning the list doesn't mistake an intentional Н/П for a
   forgotten (not_checked, gray) item. */
.results-item-not_applicable { border-left: 4px solid var(--gt-result-item-na-border); background: var(--gt-result-item-na-bg); }
.results-item-row { display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; }
.results-label { font-weight: 500; flex: 1; }
.results-state { font-size: 0.85rem; font-weight: 600; white-space: nowrap; }
/* PATH08-REUSABLE-VISUAL-ACCEPTANCE-AND-UI-CLOSURE-01: a note or a typed answer keeps the lines the mechanic
   typed. Measured on the real phone: a three-line note ran together into one paragraph, and the same rule
   was missing from the receptionist's results, the inspection page and the client report. `pre-line` keeps
   ordinary wrapping and collapses runs of spaces; only a typed line break becomes a line. */
.results-note { font-size: 0.9rem; color: var(--gt-gray); margin-top: 0.25rem; font-style: italic; white-space: pre-line; }
/* PATH08-REUSABLE-VISUAL-ACCEPTANCE-AND-UI-CLOSURE-01: what the mechanic recorded
   on a question that asked for words or for one option — shown under its
   question on the receptionist's results list instead of «✓ OK». A pasted part
   number has no break opportunity, so the value may break anywhere. Scoped to
   the receptionist list; the mechanic branch sets its own answer. */
#results-items .results-answer { margin-top: 0.25rem; font-size: 0.95rem; overflow-wrap: anywhere; }
/* T18-66B: multi-select defect list on results/wizard-recap (one line per defect + clarification) */
.results-defects { margin-top: 0.25rem; display: flex; flex-direction: column; gap: 0.15rem; }
/* T18-66D: defects are the most actionable data on this screen for a
   receptionist deciding what to tell the client — give them visual weight
   instead of blending into surrounding plain text (was unstyled, same
   weight as .results-note). Reuses the existing danger/issue color. */
.results-defect { font-size: 0.9rem; color: var(--gt-danger); font-weight: 500; }
/* T18-66D: photo thumbnail sizing was inline in the template; moved here
   unchanged (same values) so the markup stays clean — no visual change. */
.results-photo-thumb { max-width: 80px; max-height: 80px; border-radius: 3px; border: 1px solid var(--gt-photo-thumb-border); margin: 2px; vertical-align: middle; }

/* T18-68B: issue-first receptionist view. Default state (.results-filtered
   present) hides every non-issue row and collapses sections left with
   nothing to show; toggling the class off (JS in the template) reveals the
   full checklist. Scoped under #results-items, which only the receptionist
   (non-mechanic) branch of receptionist_inspection_results.html renders —
   the mechanic branch uses a separate .mech-res-item markup untouched here. */
.results-filtered .results-item:not(.results-item-issue) { display: none; }
.results-filtered .results-section:not(:has(.results-item-issue)) { display: none; }
.btn-toggle-issues { background: var(--gt-surface-muted); border: 1px solid var(--gt-border); border-radius: 6px; padding: 0.45rem 1rem; font-size: 0.9rem; font-weight: 600; cursor: pointer; color: var(--gt-result-neutral-fg); margin-bottom: 0.75rem; }
.btn-toggle-issues:hover { background: var(--gt-border); }
.results-all-clear { background: var(--gt-result-all-clear-bg); color: var(--gt-result-all-clear-fg); padding: 0.75rem 1rem; border-radius: 8px; font-weight: 600; margin-bottom: 0.75rem; }
/* T18-68B: distinct from .results-all-clear (neutral, not green) — an
   inspection still in progress with 0 issues SO FAR is not the same claim
   as "verified clean", so it must not share the reassuring green banner. */
.results-not-done { background: var(--gt-result-neutral-bg); color: var(--gt-result-neutral-fg); padding: 0.75rem 1rem; border-radius: 8px; font-weight: 600; margin-bottom: 0.75rem; }

/* --- T18-11G Slice G: Work Order Intake + Template Seed --- */
/* DS-1 Gate 1 (2026-07-17): upgraded in place to the accepted reference's
   page-heading pattern (bottom border + real spacing + eyebrow/subtitle
   support) — shared by 14 templates, so every one of them gets consistent
   heading weight with zero markup change required. See the new .gt-eyebrow/
   .gt-page-subtitle rules (end of file) for the optional pieces some pages
   now use. */
.wo-list-header { display: flex; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; gap: var(--gt-space-4); margin-bottom: var(--gt-space-5); padding-bottom: var(--gt-space-4); border-bottom: 1px solid var(--gt-border); }
.wo-list-header h1 { margin: 0; font-size: 28px; }
/* DS-1 package 2 resolver (2026-07-17): this is the EFFECTIVE
   .btn-primary declaration for plain class="btn btn-primary" markup —
   same specificity as the compound .btn.primary,.btn-primary rule
   above, but declared LATER, so it wins by source order for every
   consumer template (admin_*, inspection_template_draft_edit.html,
   work_order_intake.html, work_orders.html, etc.). Its fill
   (var(--gt-accent)) is UNCHANGED/theme-switching, Porcelain-preserving
   (matches the current live render exactly) — only its text now
   switches per theme, reusing --gt-btn-primary-fg (Porcelain: the
   existing theme-neutral --gt-ref-btn-solid-fg, byte-identical to the
   old raw #fff; Studio: the already-accepted --gt-ref-studio-bg anchor,
   since Studio's --gt-accent is a light color and white text on it
   measured only ~2.16:1). :hover's OWN fill (#1d4ed8) is a distinct,
   unrelated-to-accent historical shade that never theme-switched —
   tokenized as-is (--gt-btn-primary-hover-bg, theme-neutral, no value
   change) and its color is explicitly reverted to the existing
   theme-neutral --gt-btn-solid-fg (white) so hover keeps working in
   Studio too, instead of inheriting the now-switched dark base color
   onto a fill that stays medium-dark in both themes. */
.btn-primary { background: var(--gt-accent, #2563eb); color: var(--gt-btn-primary-fg); border: none; padding: 0.45rem 1.1rem; border-radius: 6px; font-weight: 600; cursor: pointer; text-decoration: none; display: inline-block; }
.btn-primary:hover { background: var(--gt-btn-primary-hover-bg); color: var(--gt-btn-solid-fg); }
.btn-secondary { background: var(--gt-border); color: var(--gt-text); border: none; padding: 0.45rem 1.1rem; border-radius: 6px; font-weight: 600; cursor: pointer; text-decoration: none; display: inline-block; }
.seed-section { margin: 0.5rem 0 1rem 0; display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.btn-seed { background: #f59e0b; color: #fff; border: none; padding: 0.4rem 0.9rem; border-radius: 6px; font-size: 0.85rem; font-weight: 600; cursor: pointer; }
.btn-seed:hover { background: #d97706; }
.seed-hint { font-size: 0.8rem; color: var(--gt-gray, #6b7280); }
.seed-banner { padding: 0.5rem 0.9rem; border-radius: 6px; margin-bottom: 0.75rem; font-weight: 500; font-size: 0.9rem; }
/* DS-1 package 2 resolver (2026-07-17): .seed-ok tokenized —
   background/text byte-match the already-accepted --gt-result-ok-
   badge-bg/--gt-state-success-fg exactly; only its border was genuinely
   new. .seed-info is confirmed dead (zero template consumer anywhere)
   and deliberately left untouched — out of this package's "live
   members only" scope, same class of finding as deferred #138's dead
   .rw-* selectors.
   Deferred item 144 correction (2026-07-17): --gt-ref-seed-ok-border's
   Porcelain value corrected in place (#86efac -> #166534, byte-
   identical to this same rule's own --gt-state-success-fg text color)
   — the original border value cleared its Studio pairing but measured
   only 1.28:1 against this rule's OWN Porcelain background (needed
   3:1). Studio's computed value is unchanged (same --gt-ref-studio-
   success anchor). */
.seed-ok { background: var(--gt-result-ok-badge-bg); color: var(--gt-state-success-fg); border: 1px solid var(--gt-seed-ok-border); }
/* Flash-banner auto-dismiss (2026-07-22, owner request — one shared
   principle for every one-time post-redirect notification app-wide, driven
   by the shared script in base.html, not per-page copies): [data-flash-
   banner] elements fade out on their own after a few seconds, like a toast,
   instead of sitting on the page indefinitely. Layout height collapses
   together with the opacity fade so the page doesn't leave a dead gap. */
/* Two-stage dismissal (owner-caught: animating opacity and max-height
   TOGETHER looks jerky — the text visibly reflows/squishes while it's
   still readable). Stage 1 (.is-flash-fading) fades opacity ONLY, nothing
   else moves. Stage 2 (.is-flash-dismissed), added only after the fade
   finishes, collapses the now-invisible box out of the layout — any
   jerkiness there is invisible since opacity is already 0. */
[data-flash-banner] { transition: opacity .35s ease; }
[data-flash-banner].is-flash-fading { opacity: 0; pointer-events: none; }
[data-flash-banner].is-flash-dismissed {
  transition: margin .25s ease, padding .25s ease, max-height .25s ease, border-width .25s ease;
  overflow: hidden; opacity: 0; margin: 0; padding-top: 0; padding-bottom: 0; max-height: 0; border-width: 0; pointer-events: none;
}
.seed-info { background: #fef9c3; color: #854d0e; border: 1px solid #fde047; }
.intake-header { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1rem; }
.intake-header h1 { margin: 0; }
.intake-client-select { margin-bottom: 1rem; }
.intake-form { max-width: 560px; }
.intake-input { width: 100%; box-sizing: border-box; padding: 0.45rem 0.7rem; border: 1px solid var(--gt-border, #e5e7eb); border-radius: 6px; font-size: 1rem; }
.intake-readonly { font-weight: 600; }
.form-actions { display: flex; gap: 0.75rem; align-items: center; margin-top: 1.25rem; flex-wrap: wrap; }

/* ── T18-11J Slice J: Receptionist Inspection UX Flow styles ── */
/* DS-1 package 2 resolver (2026-07-17): .intake-note tokenized — its
   text byte-matches the already-accepted --gt-result-skip-fg exactly
   (a "result state" family token being reused here for unrelated
   helper-text, matching this codebase's established practice of
   reusing tokens by exact color value rather than by original naming
   family). .intake-input's own border already resolves through
   var(--gt-border, #e5e7eb) — the raw fallback is never actually used
   (--gt-border is always defined) and introduces no theme-awareness
   problem, so it is left exactly as-is. */
.intake-note { font-size: 0.875rem; color: var(--gt-result-skip-fg); margin-bottom: 1rem; }
.task-client { font-weight: 600; }
.task-vehicle { color: #6b7280; margin-left: 0.5rem; }
.task-reason { font-size: 0.9rem; color: #374151; margin: 0.25rem 0 0.5rem; }

/* ── T18-11I Slice I: UX Hotfix styles ── */
/* T18-65A (#10): the post-completion queue banner was too weak to notice on the
   dark mechanic queue. Make it a prominent, animated success banner so the mechanic
   clearly sees the inspection was saved and the task closed. Only used on the
   mechanic queue (mechanic_queue.html). */
.completion-banner {
  display: flex; align-items: center; gap: 12px;
  background: linear-gradient(180deg, rgba(61,220,116,.20), rgba(61,220,116,.07));
  color: #B8F2D0; border: 1px solid rgba(61,220,116,.45);
  padding: 16px 18px; border-radius: 16px; margin-bottom: 18px;
  font-size: 16px; font-weight: 800; line-height: 1.35;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.10), 0 8px 24px rgba(0,0,0,.30);
  animation: completion-pop .5s cubic-bezier(.34,1.56,.64,1);
}
@keyframes completion-pop {
  0%   { opacity: 0; transform: translateY(-10px) scale(.97); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

/* ── T18-14A: Mechanic mobile / PWA prep ──────────────────────
   Distinct, large touch targets for the inspection wizard so the
   mechanic can run the flow on an Android phone. No behavior change;
   styling only. Buttons keep their value="ok" / value="issue". */
.wizard-question-card { border: 1px solid var(--gt-border); border-radius: 10px; padding: 1rem 1.1rem; background: var(--gt-surface); max-width: 640px; }
.wizard-question-text { font-size: 1.15rem; font-weight: 700; line-height: 1.35; margin-bottom: 0.6rem; color: var(--gt-text); }
.wizard-photo-hint { font-size: 0.9rem; color: #92400e; background: #fffbeb; border: 1px solid #fde68a; border-radius: 6px; padding: 0.4rem 0.6rem; margin-bottom: 0.6rem; }
.wizard-progress { font-size: 0.95rem; color: var(--gt-gray); margin-bottom: 0.5rem; }
.wizard-section-label { font-weight: 700; font-size: 1rem; margin-bottom: 0.5rem; }
.photo-required-warning { background: #fef2f2; border: 1px solid #fecaca; color: #b91c1c; }

/* Make the three answer states visually distinct (default desktop view) */
.btn-state-ok { background: #dcfce7; border-color: #16a34a; color: #15803d; font-weight: 700; }
.btn-state-issue { background: #fee2e2; border-color: #dc2626; color: #b91c1c; font-weight: 700; }
.btn-state-save-issue { background: #fef3c7; border-color: #d97706; color: #92400e; font-weight: 700; }

/* Phone-width: large finger-friendly targets for the mechanic flow */
@media (max-width: 640px) {
  .container { padding: 16px 14px; }
  h1 { font-size: 22px; }
  .mechanic-task-list,
  .wizard-question-card { max-width: 100%; }
  .btn-large { width: 100%; min-height: 52px; font-size: 1.1rem; }
  .btn-take,
  .btn-open,
  .btn-complete { min-height: 52px; font-size: 1.1rem; }
  .state-btns { gap: 0.5rem; }
  .btn-state { min-height: 60px; font-size: 1.05rem; flex-basis: 45%; }
  .check-note { font-size: 1rem; }
  .wizard-question-text { font-size: 1.2rem; }
  /* S8D camera label as a full-width tap target on phone */
  #s8d-photo-block label { display: block !important; text-align: center; min-height: 52px; line-height: 2.4; font-size: 1.05rem; }
}

/* ── T18-14B: Mechanic mobile workflow UI hotfix ──────────────
   Cleaner wizard header, prominent progress, completion card.
   Styling only; wizard behavior and backend guard unchanged. */
.insp-header-mech { margin-bottom: 0.75rem; }
.mech-title { font-size: 20px; margin: 0 0 0.2rem; }
.mech-client { font-size: 1rem; font-weight: 600; color: var(--gt-text); margin: 0 0 0.4rem; }
.mech-context { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.6rem; font-size: 0.9rem; color: var(--gt-gray); margin: 0 0 0.5rem; }
.mech-order { font-weight: 600; color: var(--gt-text); }
.mech-reason { color: var(--gt-text); }
.mech-who { color: var(--gt-gray); }

/* Prominent progress: main line large, answered count secondary */
.wizard-progress { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem 0.9rem; margin-bottom: 0.6rem; }
.wizard-progress-main { font-size: 1.25rem; font-weight: 800; color: var(--gt-text); }
.wizard-progress-sub { font-size: 0.85rem; color: var(--gt-gray); }

/* Completion state card */
.mech-complete-card { max-width: 640px; border: 1px solid #a7f3d0; background: #ecfdf5; border-radius: 12px; padding: 1.4rem 1.2rem; text-align: center; }
.mech-complete-check { font-size: 2.4rem; line-height: 1; color: #059669; }
.mech-complete-title { font-size: 1.25rem; font-weight: 800; color: #065f46; margin: 0.4rem 0 0.3rem; }
.mech-complete-sub { font-size: 0.95rem; color: #047857; margin-bottom: 1rem; }

@media (max-width: 640px) {
  .wizard-progress-main { font-size: 1.35rem; }
  .mech-complete-card .btn-complete { width: 100%; }
}

/* ── T18-14D: completed tasks in mechanic queue ───────────────
   Read-only "Завершённые" section; styling only. */
.mechanic-task-completed { border-left: 4px solid #16a34a; background: #f8fafc; }
.task-completed-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.6rem; font-size: 0.85rem; color: var(--gt-gray); margin: 0.35rem 0 0.5rem; }
.btn-open-results { background: #475569; }

/* ═══ T18-17E: Mechanic mobile — Industrial Premium ════════════════════════
   Scoped to .mech-app only; desktop light theme untouched.
   Steel Premium base · dark graphite anthracite · deep petrol/blue-teal
   primary actions · dusty copper-red defect accents · restrained green OK.
   GT brand red stays logo/brand only — never used as a UI action color here. */
.mech-app {
  /* local industrial token set — overrides only inside the mechanic shell */
  --mi-bg:        #14181E;
  --mi-bg-2:      #171C23;
  --mi-surface:   #1F262F;
  --mi-surface-2: #252D38;
  --mi-surface-3: #1A2027;
  --mi-ink:       #ECEFF3;
  --mi-ink-soft:  #AEB7C2;
  /* PATH08-REUSABLE-VISUAL-ACCEPTANCE-AND-UI-CLOSURE-01: was #7C8693 — 3.95:1 as small meta text on the cards
     (surface-2 -> surface), under WCAG AA. #8E98A5 is 4.99:1 there and still well below --mi-ink-soft. */
  --mi-ink-faint: #8E98A5;
  --mi-line:      #2C333D;
  --mi-line-2:    #242B34;
  --mi-petrol:    #4B6B72;   /* primary action — deep petrol / blue-teal */
  --mi-petrol-2:  #5C8088;   /* lighter petrol for gradient top */
  --mi-petrol-dk: #3C575D;
  /* PATH08-REUSABLE-VISUAL-ACCEPTANCE-AND-UI-CLOSURE-01: petrol used as TEXT. -2 is a fill shade and
     measured 3.2-4.2:1 as small text on the mechanic surfaces; this one is 5.1:1 or more on every one. */
  --mi-petrol-ink: #7FA3AB;
  --mi-copper:    #9A5B50;   /* defect / fault accent — dusty copper-red */
  --mi-copper-ink:#C98B7F;
  --mi-copper-bg: rgba(154,91,80,.15);
  --mi-copper-ln: rgba(154,91,80,.42);
  --mi-ok:        #6BA985;   /* restrained green */
  --mi-ok-bg:     rgba(107,169,133,.13);
  --mi-ok-ln:     rgba(107,169,133,.38);
  --mi-ok-ink:    #7BB793;   /* the restrained green used as TEXT: 5.07:1 on its chip over a card (--mi-ok was 4.29:1) */
  --mi-amber:     #E3A24E;   /* T18-66F: selected-defect accent — warm amber (attention, not "OK"-green) */
  --mi-amber-ln:  rgba(227,162,78,.45);
  --mi-radius:    16px;
  --mi-radius-lg: 20px;
  --mi-shadow:    0 1px 0 rgba(255,255,255,.03) inset, 0 10px 30px rgba(0,0,0,.42);
  --mi-font: 'Inter',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Arial,sans-serif;

  /* full-bleed dark shell over the .container padding */
  margin: -24px -28px;
  padding: 18px 16px 28px;
  min-height: calc(100vh - 0px);
  background: linear-gradient(180deg,var(--mi-bg-2),var(--mi-bg));
  color: var(--mi-ink);
  font-family: var(--mi-font);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent; /* kill the blue tap flash on Android */
  /* T18-66I: the per-load fade-in animation was removed — question→question smoothness
     is now handled by cross-document View Transitions (opted in from the wizard
     template), which crossfade without the old "slow slide-in" feel and without a
     blank flash. Non-supporting browsers just navigate normally (no regression). */
}
.mech-app * { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
.mech-app a, .mech-app button, .mech-app label, .mech-app input { -webkit-tap-highlight-color: transparent; }
.mech-app a:focus, .mech-app button:focus, .mech-app label:focus, .mech-app .mech-atile:focus { outline: none; }

/* S5: design-token bridge for the 12 owner-accepted suspension cards
   (see accepted-suspension-cards in the owner-approved reference pack).
   Those cards were authored against the prototyping tool own shadcn-style
   token names (card, primary, viz-series-N, space-N, and similar dashed
   names), which do not exist in this app own gt-dash or mi-dash token
   families. Per each card own manifest reuse_rule (Product integration may
   adapt only the outer component wrapper and design-system tokens without
   changing mechanical geometry), this block ALIASES those exact token
   names to the real mechanic-shell (mech-app) tokens; it never edits the
   copied SVG or legend markup or any per-card stroke-width or geometry
   rule. Scoped to mech-app only; the 7 viz-series hues are a small
   dedicated categorical set (not reused elsewhere) chosen for read
   contrast against the app own dark surfaces, not from the original
   prototyping tool palette (which is not shipped here); this is the one
   deliberate visual judgment call in this bridge.
   CSS-comment safety note for future editors: this paragraph avoids
   apostrophes and the slash-asterisk close sequence entirely, after two
   separate incidents where writing them literally inside this exact
   comment truncated it early and silently corrupted the rule below. Do not
   reintroduce them here; describe punctuation in words instead. */
.mech-app {
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --border:            var(--mi-line);
  --card:              var(--mi-surface);
  --card-foreground:   var(--mi-ink);
  --foreground:        var(--mi-ink);
  --muted:             var(--mi-surface-2);
  --muted-foreground:  var(--mi-ink-soft);
  --primary:           var(--mi-petrol);
  --primary-foreground:var(--mi-ink);
  --destructive:       var(--mi-copper);
  --viz-series-1: #E3A24E; /* lower/lateral arm — reuses --mi-amber's hue */
  --viz-series-2: #6BA985; /* damper / spring — reuses --mi-ok's hue */
  --viz-series-3: #6FA8DC; /* steering tie-rod */
  --viz-series-4: #C97B6D; /* anti-roll stabilizer bar */
  --viz-series-5: #B592D6; /* drop-link / strut */
  --viz-series-6: #5EC8C0; /* top mount / bearing / upper arm */
  --viz-series-7: #9AA5B1; /* secondary arm (multilink 2nd lower/upper) */
  --chart-5:      #B592D6; /* fallback target of var(--viz-series-7, var(--chart-5)) */
}

/* top bar: back left, real system logo right */
.mech-bar { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.mech-bar-title { font-size: 15px; font-weight: 700; letter-spacing: .02em; color: var(--mi-ink-soft); min-width: 0; flex-shrink: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* PATH08-REUSABLE-VISUAL-ACCEPTANCE-AND-UI-CLOSURE-01: a fixed screen name («Осмотр», «Подвеска», «Результат»)
   never gives way — on the real phone at 392 CSS px «Осмотр» was cut to «Осмо…» for 2px. The one title that
   may shrink is a vehicle name, which can be any length and is marked as such by the wizard. */
.mech-bar-title.mech-bar-title-vehicle { flex-shrink: 1; }
.mech-bar-spacer { flex: 1; }
/* MECHANIC-MOBILE-NAV-UX-01 (2026-08-06): compact, non-interactive session
   identity — one line, quiet, truncates rather than ever wrapping/clipping
   the header at 375px; never a link/button/dropdown. */
.mech-bar-identity {
  font-size: 12px; font-weight: 600; color: var(--mi-ink-faint);
  flex: 0 1 auto; min-width: 0; max-width: 34%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mech-back {
  width: 40px; height: 40px; border-radius: 12px; flex: none;
  display: flex; align-items: center; justify-content: center;
  font-size: 19px; text-decoration: none;
  color: var(--mi-ink-soft); background: var(--mi-surface-2); border: 1px solid var(--mi-line);
}
/* T18-57: top-left exit to queue — labeled (not an arrow) so it is never confused
   with the per-question "← Назад" navigation */
.mech-queue-btn {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  height: 40px; padding: 0 14px; border-radius: 12px;
  font-size: 14px; font-weight: 700; text-decoration: none;
  color: var(--mi-ink-soft); background: var(--mi-surface-2); border: 1px solid var(--mi-line);
}
/* reuse existing /static/img/gt_service_logo_header.png at header proportions */
.mech-logo { height: 30px; width: auto; display: block; opacity: .95; }

/* context card */
.mech-ctx {
  border: 1px solid var(--mi-line); border-radius: var(--mi-radius-lg);
  padding: 18px 18px 16px; position: relative; overflow: hidden;
  background: linear-gradient(180deg,var(--mi-surface-2),var(--mi-surface));
  box-shadow: var(--mi-shadow);
}
.mech-ctx::before { content:""; position:absolute; left:0; top:0; bottom:0; width:3px; background: var(--mi-petrol); opacity:.85; }
.mech-ctx-veh { font-size: 23px; font-weight: 800; letter-spacing: -.01em; }
.mech-ctx-client { font-size: 15px; color: var(--mi-ink-soft); margin-top: 3px; }
.mech-ctx-meta { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 14px; }
.mech-chip {
  font-size: 12.5px; font-weight: 600; padding: 5px 11px; border-radius: 999px;
  background: var(--mi-surface-3); border: 1px solid var(--mi-line-2); color: var(--mi-ink-soft);
}
.mech-chip-live { background: var(--mi-ok-bg); border-color: var(--mi-ok-ln); color: var(--mi-ok-ink); }
.mech-ctx-mech { margin-top: 13px; padding-top: 13px; border-top: 1px solid var(--mi-line-2); font-size: 13.5px; color: var(--mi-ink-faint); }
.mech-ctx-mech b { color: var(--mi-ink-soft); font-weight: 700; }

/* MECHANIC-MOBILE-NAV-UX-01 (2026-08-06): profile screen — identity card +
   the app's only logout control, at the bottom of the screen. Full-width,
   clearly labeled, but neutral (not a vivid gradient CTA — that language is
   reserved for primary inspection actions elsewhere in the app). */
.mech-profile-card {
  border: 1px solid var(--mi-line); border-radius: var(--mi-radius-lg);
  padding: 20px 18px; text-align: center;
  background: linear-gradient(180deg,var(--mi-surface-2),var(--mi-surface));
  box-shadow: var(--mi-shadow);
}
.mech-profile-avatar {
  width: 56px; height: 56px; margin: 0 auto 12px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--mi-surface-3); border: 1px solid var(--mi-line); color: var(--mi-petrol-2);
}
.mech-profile-name { font-size: 19px; font-weight: 800; letter-spacing: -.01em; color: var(--mi-ink); }
.mech-profile-role { font-size: 13px; color: var(--mi-ink-faint); margin-top: 4px; }
.mech-profile-logout-form { margin-top: 28px; }
.mech-profile-logout-btn {
  width: 100%; min-height: 52px; padding: 0 16px; font-size: 15.5px; font-weight: 700;
  color: var(--mi-copper-ink); border: 1px solid var(--mi-copper-ln); background: var(--mi-copper-bg);
}
.mech-profile-logout-btn:hover { filter: brightness(1.08); }

/* MECHANIC-MOBILE-NAV-UX-01 (2026-08-06): honest empty state — outlined
   icon + headline + support copy, shared by every mechanic list screen
   (Очередь/В работе/История) instead of a single muted line of text. */
.mech-empty-state {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 8px; padding: 46px 20px 40px; color: var(--mi-ink-faint);
}
.mech-empty-ic { width: 52px; height: 52px; opacity: .5; }
.mech-empty-headline { font-size: 16px; font-weight: 700; color: var(--mi-ink-soft); }
.mech-empty-subcopy { font-size: 13.5px; max-width: 260px; }

/* section caption (e.g. ТЕКУЩИЙ ПРОБЕГ) */
.mech-cap { font-size: 13px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--mi-ink-faint); margin: 22px 4px 9px; }

/* mileage card */
.mech-mileage {
  border: 1px solid var(--mi-line); border-radius: var(--mi-radius);
  padding: 16px 18px; box-shadow: var(--mi-shadow);
  background: linear-gradient(180deg,var(--mi-surface-2),var(--mi-surface));
}
.mech-mileage-prev { font-size: 12.5px; color: var(--mi-ink-faint); margin-bottom: 10px; }
.mech-mileage-prev b { color: var(--mi-ink-soft); font-weight: 700; }
.mech-mileage-vin { font-size: 12px; color: var(--mi-ink-faint); margin-bottom: 10px; }
.mech-mileage-input {
  width: 100%; box-sizing: border-box; font-size: 32px; font-weight: 800; text-align: center;
  padding: 12px 14px; border-radius: 13px; color: var(--mi-ink);
  background: var(--mi-surface-3); border: 1.5px solid var(--mi-line);
  -moz-appearance: textfield; font-family: var(--mi-font);
}
.mech-mileage-input::-webkit-outer-spin-button,
.mech-mileage-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.mech-mileage-input:focus { outline: none; border-color: var(--mi-petrol-2); }
.mech-mileage-input::placeholder { color: var(--mi-ink-faint); font-weight: 600; }

/* section rows */
.mech-sec-list { margin-top: 14px; display: flex; flex-direction: column; gap: 8px; }
.mech-sec-row {
  display: flex; align-items: center; gap: 11px; border: 1px solid var(--mi-line-2);
  border-radius: 13px; padding: 13px 14px; font-size: 14.5px; font-weight: 600;
  color: var(--mi-ink-soft); background: var(--mi-surface-3);
}
.mech-sec-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--mi-petrol-2); flex: none; }

/* primary CTA — deep petrol / blue-teal */
.mech-cta {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; min-height: 60px; margin-top: 20px; border: 1px solid rgba(255,255,255,.08);
  border-radius: 16px; font-size: 18px; font-weight: 700; letter-spacing: .01em; cursor: pointer;
  color: #F4F8F8; background: linear-gradient(180deg,var(--mi-petrol-2),var(--mi-petrol));
  box-shadow: 0 8px 22px rgba(0,0,0,.38); font-family: var(--mi-font); text-decoration: none;
}
.mech-cta:active { background: linear-gradient(180deg,var(--mi-petrol),var(--mi-petrol-dk)); }

/* O2 / OB-SEC-003: the reserve device on the PIN screen. Same size and hit
   area as the primary CTA — it is an equal choice, not a lesser one — but a
   quieter surface, so the личный телефон reads as the primary device
   DC-SEC-005 says it is. Tokens only, no literal colour. */
.mech-cta-secondary {
  margin-top: 12px; color: var(--mi-ink); background: var(--mi-surface-3);
  border: 1px solid var(--mi-line-2); box-shadow: none;
}
.mech-cta-secondary:active { background: var(--mi-surface-2); }

/* progress / question */
.mech-progress { margin: 4px 0 0; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; }
.mech-progress-pos { font-size: 15px; font-weight: 700; color: var(--mi-ink); }
.mech-pbar { flex-basis: 100%; height: 12px; border-radius: 999px; background: var(--mi-surface-3); margin-top: 9px; overflow: hidden; border: 1px solid var(--mi-line-2); }
.mech-pbar > i { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg,#2E9E56,#3DDC74); }

/* R6U: low-friction pause action — quiet, not a primary CTA (pausing is not
   the "success" action on this screen, so it must not visually compete with
   answer buttons/mech-cta). */
.mech-pause-form { flex: none; margin: 0; }
.mech-pause-btn {
  border: 1px solid var(--mi-line-2); border-radius: 999px; padding: 6px 14px;
  font-size: 13px; font-weight: 600; color: var(--mi-ink-soft); background: var(--mi-surface-3);
  cursor: pointer; font-family: var(--mi-font);
}
.mech-pause-btn:active { background: var(--mi-surface-2); }
.mech-paused-since { font-size: 13.5px; color: var(--mi-ink-faint); margin-top: 10px; font-weight: 600; }
.mech-sec-pill {
  display: flex; align-items: center; gap: 8px; margin: 12px 0 0;
  font-size: 13px; font-weight: 700; color: var(--mi-petrol-ink);
  background: linear-gradient(180deg, rgba(255,255,255,.045), rgba(255,255,255,0)), rgba(75,107,114,.14);
  border: 1px solid rgba(255,255,255,.08); padding: 10px 14px; border-radius: 13px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.05);
}
.mech-sec-pill .mech-sec-count { margin-left: auto; color: var(--mi-ink-soft); opacity: .8; font-weight: 600; }
.mech-q-card {
  border: 1px solid rgba(255,255,255,.07); border-radius: 20px;
  padding: 20px 18px; margin-top: 14px;
  background: linear-gradient(180deg, rgba(255,255,255,.035), rgba(255,255,255,0)),
              linear-gradient(180deg, var(--mi-surface-2), var(--mi-surface));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.06), 0 12px 34px rgba(0,0,0,.36);
}
.mech-q-text { font-size: 20px; font-weight: 700; line-height: 1.32; letter-spacing: -.01em; }
.mech-note {
  margin-top: 16px; width: 100%; border: 1px solid var(--mi-line); border-radius: 12px;
  background: var(--mi-surface-3); padding: 12px 13px; font-size: 14px; color: var(--mi-ink);
  font-family: var(--mi-font); min-height: 48px; resize: vertical;
}
.mech-note::placeholder { color: var(--mi-ink-faint); }

/* integrated photo area */
.mech-photo { margin-top: 14px; }
.mech-photo-status { font-size: 13px; min-height: 1.3em; margin-bottom: 8px; color: var(--mi-ink-soft); }
.mech-photo-actions { display: flex; flex-wrap: wrap; gap: 9px; }
/* T18-66F/G: up-front photo hint on required-photo questions. Default = "photo needed
   here" (warm copper). T18-66G .is-done variant = "photo already attached" (calm green),
   shown in edit mode when the item already has a photo. */
.mech-photo-req-note {
  margin: 2px 0 12px; padding: 9px 12px; border-radius: 11px;
  background: var(--mi-copper-bg); border: 1px solid var(--mi-copper-ln);
  color: var(--mi-copper-ink); font-size: 13.5px; font-weight: 600;
}
.mech-photo-req-note.is-done {
  background: var(--mi-ok-bg); border-color: var(--mi-ok-ln); color: var(--mi-ok);
}
/* compact conditional warning — only rendered when relevant, inside the card */
.mech-photo-warn {
  display: flex; align-items: center; gap: 9px; margin-top: 14px; padding: 11px 13px;
  border-radius: 12px; font-size: 13px; font-weight: 600;
  background: var(--mi-copper-bg); border: 1px solid var(--mi-copper-ln); color: var(--mi-copper-ink);
}

/* answer tiles — large, one-tap */
.mech-answers { margin-top: 18px; display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.mech-atile {
  position: relative;
  min-height: 84px; border-radius: 18px; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 8px; cursor: pointer;
  font-size: 16px; font-weight: 700; border: 1px solid; font-family: var(--mi-font);
  transition: transform .13s ease; -webkit-tap-highlight-color: transparent;
}
.mech-atile:active { transform: scale(.965); }
.mech-atile .ic {
  width: 32px; height: 32px; border-radius: 50%; font-size: 17px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16);
}
/* T18-66G: the per-tile .mech-photo-flag 📷 icon was removed (owner phone review) —
   the up-front .mech-photo-req-note hint is now the single photo reminder. */
.mech-atile-ok {
  background: linear-gradient(180deg, rgba(61,220,116,.17), rgba(61,220,116,.05));
  border-color: rgba(61,220,116,.30); color: #86E6AB;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.08), 0 6px 18px rgba(0,0,0,.24);
}
.mech-atile-ok .ic { background: rgba(61,220,116,.22); color: #A6EFC4; }
.mech-atile-issue {
  background: linear-gradient(180deg, rgba(224,122,110,.16), rgba(224,122,110,.05));
  border-color: rgba(224,122,110,.32); color: #EAA79D;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.07), 0 6px 18px rgba(0,0,0,.24);
}
.mech-atile-issue .ic { background: rgba(224,122,110,.22); color: #F2BDB4; }
/* T18-20C: manual N/P (не применимо) — neutral, full-width, smaller than ok/issue */
.mech-answers-na { grid-template-columns: 1fr; margin-top: 12px; }
.mech-atile-na {
  min-height: 58px; font-size: 15px; flex-direction: row; gap: 9px;
  background: linear-gradient(180deg, rgba(255,255,255,.05), rgba(255,255,255,.01));
  border-color: rgba(255,255,255,.10); color: var(--mi-ink-soft);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.05), 0 4px 12px rgba(0,0,0,.18);
}
.mech-atile-na .ic { width: 26px; height: 26px; font-size: 15px; background: rgba(255,255,255,.07); color: var(--mi-ink-faint); }
/* T18-65A (#2/#3/#4): single full-width save button for choice/text questions.
   Row layout (icon + label centered), full width, and sticky above the bottom nav
   so it is always reachable on long option lists / after typing a text answer. */
/* T18-66F: was inheriting the 2-column .mech-answers grid → the save button sat in
   one column (half width) and "Сохранить ответ" wrapped to two lines on the phone.
   Force a single full-width column so it reads on one line, like the bright answer tile. */
.mech-answers-save { margin-top: 16px; grid-template-columns: 1fr; }
.mech-atile-save {
  width: 100%; flex-direction: row; gap: 10px; min-height: 60px;
  position: sticky; bottom: 84px; z-index: 5;
}
.mech-atile-save .ic { width: 30px; height: 30px; font-size: 17px; }
/* T18-67B: confirm-before-camera modal ("what to photograph"). Bottom-sheet style,
   consistent with the app's dark surface/line tokens. Hidden by default; JS toggles
   display:flex. Reuses .mech-atile-ok for the primary button's color language, but
   NOT .mech-atile-save (its position:sticky is meaningless/conflicting inside a
   fixed overlay) — full width via its own rule instead. */
.mech-photo-instruction-overlay {
  display: none; position: fixed; inset: 0; background: rgba(10,13,17,.62);
  align-items: flex-end; justify-content: center; z-index: 60; padding: 0;
}
.mech-photo-instruction-dialog {
  width: 100%; max-width: 480px; background: var(--mi-surface);
  border: 1px solid var(--mi-line); border-radius: var(--mi-radius-lg) var(--mi-radius-lg) 0 0;
  padding: 20px 18px calc(20px + env(safe-area-inset-bottom, 0px));
  box-shadow: var(--mi-shadow);
}
.mech-photo-instruction-title { font-size: 16px; font-weight: 800; color: var(--mi-ink); margin-bottom: 8px; }
.mech-photo-instruction-text { font-size: 14.5px; color: var(--mi-ink-soft); line-height: 1.45; margin-bottom: 18px; }
.mech-photo-instruction-actions { display: flex; flex-direction: column; gap: 8px; }
.mech-photo-instruction-shoot { width: 100%; flex-direction: row; gap: 10px; min-height: 56px; }
/* T18-67C: owner phone review — Cancel was 44px vs Shoot's 56px, mismatched sizes
   read as sloppy. Same min-height + same font-size now, only the fill/border/color
   distinguish primary vs secondary. */
.mech-photo-instruction-cancel {
  width: 100%; min-height: 56px; border-radius: 14px; border: 1px solid var(--mi-line);
  background: transparent; color: var(--mi-ink-faint); font-size: 16px; font-weight: 700;
  font-family: var(--mi-font); cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.mech-photo-instruction-cancel:active { transform: scale(.98); }
/* T18-56 B4: choice question radio list */
.mech-choices { display: flex; flex-direction: column; gap: 0; margin-top: 14px; border: 1px solid var(--mi-line); border-radius: 13px; overflow: hidden; }
.mech-choice-opt { display: flex; align-items: center; gap: 12px; padding: 14px 15px; font-size: 15px; font-weight: 600; color: var(--mi-ink); cursor: pointer; border-bottom: 1px solid var(--mi-line-2); }
.mech-choice-opt:last-child { border-bottom: none; }
.mech-choice-opt input[type=radio] { width: 20px; height: 20px; accent-color: var(--mi-petrol-2); flex: none; }
.mech-choice-opt input[type=checkbox] { width: 20px; height: 20px; accent-color: var(--mi-petrol-2); flex: none; }
.mech-choice-opt:has(input:checked) { background: var(--mi-ok-bg); color: var(--mi-ok); }
/* T18-57: issue-path defect list (inline, no native select) */
.mech-defect-list { margin-top: 14px; }
.mech-defect-title { font-size: 13px; font-weight: 700; color: var(--mi-ink-faint); margin-bottom: 6px; }
.mech-defect-list .mech-choices { margin-top: 0; }
.mech-defect-hint { display: none; margin-top: 8px; font-size: 13px; font-weight: 600; color: var(--mi-issue, #c0564f); }
/* T18-65D: multi-select defect row (checkbox) + nested per-defect clarification
   sub-panel (progressive disclosure, shown only when the defect is checked). */
.mech-defect-row { border-bottom: 1px solid var(--mi-line-2); }
.mech-defect-row:last-child { border-bottom: none; }
.mech-defect-row .mech-choice-opt { border-bottom: none; }
/* T18-66F: a selected DEFECT is a fault, not an "OK" — so no green full-width block.
   Highlight only the label text + the checkbox in warm amber (attention), no row fill.
   Overrides the generic green .mech-choice-opt:has(input:checked) for defect rows only. */
.mech-defect-row > .mech-choice-opt:has(input:checked) { background: transparent; color: var(--mi-amber); }
.mech-defect-row > .mech-choice-opt input[type=checkbox] { accent-color: var(--mi-amber); }
.mech-clarify-wrap { margin: 0 12px 12px; padding-left: 12px; border-left: 2px solid var(--mi-line); }
.mech-clarify-title { font-size: 12.5px; font-weight: 700; color: var(--mi-ink-faint); margin-bottom: 6px; }
.mech-clarify-wrap .mech-choices { margin-top: 0; }
/* T18-66F: collapsed clarification summary chip — after the mechanic picks a
   clarification, the radio list folds into this one-line chip so a screen with
   several defects stays short. Tap to re-open the list. */
.mech-clarify-summary {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 2px; padding: 7px 12px; border-radius: 11px;
  background: rgba(227,162,78,.14); border: 1px solid var(--mi-amber-ln);
  color: var(--mi-amber); font-size: 13.5px; font-weight: 700;
  font-family: var(--mi-font); cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.mech-clarify-summary .edit { color: var(--mi-ink-faint); font-weight: 600; }
/* T18-57: mechanic bottom navigation — premium dark bar with a glowing liquid blob */
.mech-nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  display: flex; align-items: stretch;
  background: rgba(20,24,30,.62);
  -webkit-backdrop-filter: blur(24px) saturate(1.5); backdrop-filter: blur(24px) saturate(1.5);
  border-top: 1px solid rgba(255,255,255,.08);
  padding: 8px 6px calc(8px + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -10px 30px rgba(0,0,0,.30);
}
.mech-nav-drop {
  position: absolute; left: 0; top: 14px; width: 46px; height: 46px; border-radius: 50%;
  /* glassy water-bead: bright top-left highlight fading to translucent edge */
  background:
    radial-gradient(circle at 36% 28%, rgba(255,255,255,.62), rgba(255,255,255,.14) 46%, rgba(255,255,255,.03) 78%);
  border: 1px solid rgba(255,255,255,.20);
  box-shadow:
    inset 0 2px 4px rgba(255,255,255,.45),
    inset 0 -5px 9px rgba(0,0,0,.20),
    0 5px 16px rgba(0,0,0,.30),
    0 0 0 1px rgba(170,200,255,.14),
    0 0 10px rgba(150,190,255,.12);
  -webkit-backdrop-filter: blur(10px) saturate(1.3); backdrop-filter: blur(10px) saturate(1.3);
  transition: transform .55s cubic-bezier(.5,1.4,.5,1);
  will-change: transform; pointer-events: none;
  animation: mech-drop-breathe 3.2s ease-in-out infinite;
}
/* bright specular reflection — makes it read as a living glass droplet, not a grey disc */
.mech-nav-drop::before {
  content: ""; position: absolute; top: 6px; left: 11px; width: 15px; height: 10px;
  border-radius: 50%; transform: rotate(-18deg);
  background: radial-gradient(circle, rgba(255,255,255,.9), rgba(255,255,255,0) 72%);
  filter: blur(.5px);
}
/* small secondary glint bottom-right for depth */
.mech-nav-drop::after {
  content: ""; position: absolute; bottom: 8px; right: 10px; width: 6px; height: 6px;
  border-radius: 50%; background: radial-gradient(circle, rgba(255,255,255,.5), rgba(255,255,255,0) 70%);
}
@keyframes mech-drop-breathe {
  0%, 100% { box-shadow: inset 0 2px 4px rgba(255,255,255,.45), inset 0 -5px 9px rgba(0,0,0,.20), 0 5px 16px rgba(0,0,0,.30), 0 0 0 1px rgba(170,200,255,.14), 0 0 10px rgba(150,190,255,.12); }
  50%      { box-shadow: inset 0 2px 5px rgba(255,255,255,.60), inset 0 -5px 10px rgba(0,0,0,.22), 0 6px 20px rgba(0,0,0,.34), 0 0 0 1px rgba(180,205,255,.20), 0 0 14px rgba(160,195,255,.18); }
}
.mech-nav-item {
  position: relative; z-index: 1; flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 5px;
  padding: 6px 2px; background: none; border: none; cursor: pointer; text-decoration: none;
  color: var(--mi-ink-faint); font-family: var(--mi-font); font-size: 10.5px; font-weight: 700;
  letter-spacing: .01em; -webkit-tap-highlight-color: transparent;
}
.mech-nav-ic { position: relative; width: 46px; height: 46px; display: flex; align-items: center; justify-content: center; }
.mech-nav-ic svg { width: 23px; height: 23px; transition: transform .3s ease; }
.mech-nav-item.is-active { color: #F4F8F8; }
.mech-nav-item.is-active .mech-nav-ic svg { transform: translateY(-1px) scale(1.06); animation: mech-nav-pop .5s cubic-bezier(.34,1.56,.64,1); }
.mech-nav-item.is-soon { color: var(--mi-ink-faint); opacity: .62; }
.mech-nav-lbl { line-height: 1; }
/* delicate "coming" dot instead of loud СКОРО badges */
.mech-nav-item.is-soon .mech-nav-ic::after {
  content: ""; position: absolute; top: 9px; right: 9px; width: 5px; height: 5px; border-radius: 50%;
  background: #E4B75A; box-shadow: 0 0 5px rgba(228,183,90,.55);
}
/* tactile press feedback (paired with a short haptic) — overrides resting transform */
.mech-nav-item.is-press .mech-nav-ic svg { transform: scale(.82); }
@keyframes mech-nav-pop { 0% { transform: scale(.72); opacity: .5; } 62% { transform: scale(1.14); } 100% { transform: translateY(-1px) scale(1.06); } }
.mech-nav-hint {
  position: absolute; left: 50%; top: -38px; transform: translateX(-50%) translateY(6px);
  background: var(--mi-surface-3); border: 1px solid var(--mi-line); color: var(--mi-ink-soft);
  font-size: 12.5px; font-weight: 700; padding: 7px 14px; border-radius: 12px; white-space: nowrap;
  opacity: 0; pointer-events: none; transition: opacity .22s ease, transform .22s ease; box-shadow: var(--mi-shadow);
}
.mech-nav-hint.show { opacity: 1; transform: translateX(-50%) translateY(0); }
/* keep answer buttons clear of the fixed bottom nav on auto-scroll */
.mech-q-card form { scroll-margin-bottom: 104px; }
/* T18-57: back/forward edit navigation + editing banner */
.mech-editnav { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin: 10px 0 0; }
.mech-editnav a { display: inline-flex; align-items: center; justify-content: center; line-height: 1; font-size: 14px; font-weight: 700; color: var(--mi-ink-soft); text-decoration: none; padding: 11px 18px; border: 1px solid rgba(255,255,255,.12); border-radius: 13px; background: linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.01)); box-shadow: inset 0 1px 0 rgba(255,255,255,.08); }
.mech-edit-banner { background: rgba(217,165,65,.15); border: 1px solid rgba(217,165,65,.5); border-left: 4px solid #D9A441; border-radius: 10px; padding: 10px 13px; font-size: 14px; font-weight: 700; color: #E4B75A; margin: 10px 0 0; }
/* T18-57: one thumbnail per taken photo */
.mech-previews { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.mech-previews img { width: 72px; height: 72px; object-fit: cover; border-radius: 10px; border: 1px solid var(--mi-line); }
/* T18-57: existing (already-saved) photos shown on edit/revisit */
.mech-existing-photos { margin-bottom: 12px; }
.mech-existing-label { font-size: 13px; font-weight: 700; color: var(--mi-ink-faint); margin-bottom: 6px; }
.mech-existing-photos .mech-previews { margin-top: 0; }
/* T18-57: cancel an accidental "Неисправность" */
.mech-answers-cancel { margin-top: 10px; text-align: center; }
.mech-cancel-btn { background: none; border: none; color: var(--mi-ink-faint); font-size: 14px; font-weight: 600; padding: 8px 16px; cursor: pointer; }
/* T18-56 U2: collapsible note toggle */
.mech-note-toggle { display: inline-block; margin-top: 14px; font-size: 13px; font-weight: 600; color: var(--mi-petrol-ink); text-decoration: none; cursor: pointer; }
/* T18-56 U1: photo required badge row above answer tiles */
.mech-photo-req-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 14px; }
.mech-photo-req-badge { font-size: .8rem; font-weight: 700; color: var(--mi-ok); text-align: center; padding: 4px 0; }

/* warning banners (page-level errors) */
.mech-warn {
  margin: 0 0 14px; padding: 12px 14px; border-radius: 13px; font-size: 14px; font-weight: 600;
  background: var(--mi-copper-bg); border: 1px solid var(--mi-copper-ln); color: var(--mi-copper-ink);
}
.mech-warn-ok { background: var(--mi-ok-bg); border-color: var(--mi-ok-ln); color: var(--mi-ok); }

/* T18-62: compact soft browser-compatibility notice — recommendation, not an
   error state. Reuses the copper warning palette but stays smaller/quieter
   than .mech-warn so it never reads as a blocking failure on a working page. */
.mech-browser-warn {
  margin: 0 0 14px; padding: 10px 13px; border-radius: 12px; font-size: 12.5px; line-height: 1.4;
  background: var(--mi-copper-bg); border: 1px solid var(--mi-copper-ln); color: var(--mi-copper-ink);
}
.mech-browser-warn-title { font-weight: 700; }
.mech-browser-warn-sub { margin-top: 3px; opacity: .85; font-weight: 500; }

/* S5: suspension topology selector screen. All colors/spacing reuse the
   existing --mi-* mechanic-shell tokens — no new palette. */
.mech-s5-progress {
  display: grid; grid-template-columns: repeat(5, minmax(0,1fr)); gap: 4px; margin: 4px 0 18px;
}
.mech-s5-progress span { height: 4px; border-radius: 999px; background: var(--mi-surface-3); }
.mech-s5-progress span.is-done { background: var(--mi-petrol-2); }
.mech-s5-stagehead { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.mech-s5-stagehead h2 { font-size: 19px; font-weight: 800; margin: 0 0 4px; letter-spacing: -.01em; }
.mech-s5-stagehead p { margin: 0; font-size: 13.5px; color: var(--mi-ink-soft); }
.mech-s5-back {
  flex: none; border: 1px solid var(--mi-line-2); border-radius: 999px; padding: 7px 14px;
  font-size: 13px; font-weight: 700; color: var(--mi-ink-soft); background: var(--mi-surface-3);
  cursor: pointer; font-family: var(--mi-font); text-decoration: none;
}
.mech-s5-choices { display: grid; gap: 10px; }
.mech-s5-choice {
  display: block; width: 100%; text-align: left; cursor: pointer; font-family: var(--mi-font);
  border: 1px solid rgba(255,255,255,.08); border-radius: 16px; padding: 14px 16px;
  background: linear-gradient(180deg, rgba(255,255,255,.03), rgba(255,255,255,0)), var(--mi-surface-2);
  color: var(--mi-ink);
}
.mech-s5-choice:active { transform: scale(.98); }
.mech-s5-choice strong { display: block; font-size: 15.5px; font-weight: 700; }
.mech-s5-choice span { display: block; margin-top: 3px; font-size: 13px; color: var(--mi-ink-soft); }
.mech-s5-choice.is-selected { border-color: var(--mi-petrol-2); background: linear-gradient(180deg, rgba(75,107,114,.24), rgba(75,107,114,.06)); }
.mech-s5-card-frame {
  border: 1px solid var(--mi-line); border-radius: 16px; padding: 14px; margin-top: 4px;
  background: var(--mi-surface); overflow-x: auto;
}
.mech-s5-modifiers { display: grid; gap: 10px; margin: 4px 0 18px; }
.mech-s5-modifier {
  display: flex; align-items: center; gap: 12px; padding: 13px 15px; border-radius: 14px;
  border: 1px solid var(--mi-line); background: var(--mi-surface-2); cursor: pointer;
}
.mech-s5-modifier input { width: 22px; height: 22px; accent-color: var(--mi-petrol-2); flex: none; }
.mech-s5-modifier span { font-size: 14.5px; font-weight: 600; }
.mech-s5-summary-card { border: 1px solid var(--mi-line); border-radius: 16px; padding: 16px; background: var(--mi-surface-2); display: grid; gap: 14px; }
.mech-s5-summary-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.mech-s5-summary-row p:first-child { margin: 0 0 3px; font-size: 12px; color: var(--mi-ink-faint); text-transform: uppercase; letter-spacing: .03em; }
.mech-s5-summary-row p:last-child { margin: 0; font-size: 15px; font-weight: 700; }
.mech-s5-note { margin: 14px 0 0; font-size: 13px; color: var(--mi-ink-faint); line-height: 1.5; }
.mech-s5-locked {
  margin: 0 0 14px; padding: 12px 14px; border-radius: 13px; font-size: 13.5px; font-weight: 600;
  background: var(--mi-copper-bg); border: 1px solid var(--mi-copper-ln); color: var(--mi-copper-ink);
}
.mech-s5-hidden { display: none; }

/* completion */
.mech-done-card {
  border: 1px solid var(--mi-line); border-radius: 24px; padding: 30px 22px; text-align: center;
  background: linear-gradient(180deg,var(--mi-surface-2),var(--mi-surface)); box-shadow: var(--mi-shadow);
}
/* T18-65B (#9): quiet "return to inspection" link under the finish button */
.mech-done-back { display: inline-block; margin-top: 14px; font-size: 14px; font-weight: 600; color: var(--mi-ink-faint); text-decoration: none; }
.mech-done-check {
  width: 78px; height: 78px; border-radius: 50%; margin: 0 auto 18px;
  display: flex; align-items: center; justify-content: center; font-size: 40px;
  background: var(--mi-ok-bg); border: 1.5px solid var(--mi-ok-ln); color: var(--mi-ok);
}
.mech-done-title { font-size: 23px; font-weight: 800; }
.mech-done-sub { font-size: 14.5px; color: var(--mi-ink-soft); margin-top: 7px; }
.mech-tally { display: flex; gap: 10px; margin-top: 20px; }
.mech-tally > div { flex: 1; border-radius: 14px; padding: 13px 8px; border: 1px solid var(--mi-line-2); background: var(--mi-surface-3); }
.mech-tally .n { font-size: 24px; font-weight: 800; }
.mech-tally .t { font-size: 12px; font-weight: 600; color: var(--mi-ink-faint); margin-top: 2px; }
.mech-tally .ok .n { color: var(--mi-ok); }
.mech-tally .is .n { color: var(--mi-copper-ink); }
.mech-issues { margin-top: 18px; text-align: left; display: flex; flex-direction: column; gap: 7px; }
.mech-issues .h { font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--mi-ink-faint); }
.mech-ilist {
  display: flex; align-items: center; gap: 9px; font-size: 13.5px; color: var(--mi-ink-soft);
  padding: 9px 11px; border-radius: 11px; background: var(--mi-copper-bg); border: 1px solid var(--mi-copper-ln);
}
.mech-ilist .d { width: 7px; height: 7px; border-radius: 50%; background: var(--mi-copper); flex: none; }

/* queue list */
.mech-queue-head { margin-bottom: 16px; }
.mech-queue-title { font-size: 22px; font-weight: 800; letter-spacing: -.01em; }
.mech-queue-sub { font-size: 13.5px; color: var(--mi-ink-faint); margin-top: 4px; }
.mech-queue-sub a { color: var(--mi-petrol-ink); text-decoration: none; }
.mech-name-form { display: flex; flex-direction: column; gap: 14px; margin-top: 20px; }
.mech-name-input {
  width: 100%; box-sizing: border-box; font-size: 17px; padding: 14px 16px; border-radius: 13px;
  color: var(--mi-ink); background: var(--mi-surface-3); border: 1.5px solid var(--mi-line); font-family: var(--mi-font);
}
.mech-name-input:focus { outline: none; border-color: var(--mi-petrol-2); }
.mech-name-input::placeholder { color: var(--mi-ink-faint); }
.mech-sectitle { font-size: 13px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--mi-ink-faint); margin: 22px 2px 10px; }
.mech-list { display: flex; flex-direction: column; gap: 11px; }
.mech-card {
  border: 1px solid var(--mi-line); border-radius: var(--mi-radius); padding: 16px 16px;
  background: linear-gradient(180deg,var(--mi-surface-2),var(--mi-surface)); box-shadow: var(--mi-shadow);
}
.mech-card-client { font-size: 17px; font-weight: 700; }
.mech-card-veh { font-size: 14px; color: var(--mi-ink-soft); margin-top: 2px; }
.mech-card-reason { font-size: 13px; color: var(--mi-ink-faint); margin-top: 7px; }
.mech-card-meta { font-size: 12.5px; color: var(--mi-ink-faint); margin-top: 7px; }
.mech-card-meta.pool { color: var(--mi-petrol-ink); font-weight: 600; }
.mech-card .mech-cta { min-height: 52px; font-size: 16px; margin-top: 14px; }
.mech-card-done { border-left: 3px solid var(--mi-ok); }
/* PATH08-REUSABLE-VISUAL-ACCEPTANCE-AND-UI-CLOSURE-01: text on a task card meets WCAG AA in every state.
   A paused card was faded whole (the legacy `.mechanic-task-paused { opacity: .85 }`), which put its name at
   3.26:1 and «Возобновить осмотр» at 3.85:1; the pause is already said by its badge, so in the mechanic shell
   the card keeps full strength and the badge takes a lighter violet (#8B7FC0 was 4.09:1 on the card).
   The completed line took the desktop grey; here it takes the mechanic's own faint ink. */
.mech-app .mechanic-task-paused { opacity: 1; }
.mech-app .task-paused-badge { color: #A197D1; }
.mech-app .task-completed-meta { color: var(--mi-ink-faint); }
/* PATH08-REUSABLE-VISUAL-ACCEPTANCE-AND-UI-CLOSURE-01, the same measurement on three more mechanic surfaces:
   - «📷 Нужно фото — камера откроется…» was copper ink on its own copper-tinted note, 4.36:1; #D29A8F is 5.10:1
     there (the done state keeps its own colour);
   - «Осмотр пройден» and the line under it kept the light theme's greens (#065f46, #047857) on the dark card —
     1.89:1 and 2.64:1; the mechanic's own green and soft ink are 6.24:1 and 7.15:1;
   - a results row that is not «В норме» or «Проблема» was faded whole to .65, which put its words at 3.04:1 and
     made a mechanic's deliberate «Н/П» look like a question nobody answered. The row keeps full strength; its
     state glyph still carries the quieter colour. */
.mech-app .mech-photo-req-note:not(.is-done) { color: #D29A8F; }
.mech-app .mech-complete-title { color: var(--mi-ok-ink); }
.mech-app .mech-complete-sub { color: var(--mi-ink-soft); }
.mech-app .mech-res-item-not_checked { opacity: 1; }
.mech-empty { font-size: 14.5px; color: var(--mi-ink-faint); padding: 18px 4px; }

/* T18-17F: mechanic inspection result page */
.mech-res-summary { margin: 18px 0 20px; }
.mech-res-title { font-size: 19px; font-weight: 800; color: var(--mi-ink); letter-spacing: -.01em; margin-bottom: 11px; }
.mech-res-counts { display: flex; flex-wrap: wrap; gap: 8px; }
.mech-res-badge { font-size: 13px; font-weight: 700; padding: 5px 12px; border-radius: 999px; border: 1px solid transparent; }
.mech-res-ok   { background: var(--mi-ok-bg); border-color: var(--mi-ok-ln); color: var(--mi-ok); }
.mech-res-issue { background: var(--mi-copper-bg); border-color: var(--mi-copper-ln); color: var(--mi-copper-ink); }
.mech-res-nc    { background: rgba(124,134,147,.10); border-color: rgba(124,134,147,.25); color: var(--mi-ink-faint); }
.mech-res-skipped { background: rgba(99,140,185,.13); border-color: rgba(99,140,185,.32); color: #8bb8d8; }
.mech-res-section { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.mech-res-item {
  padding: 11px 13px; border-radius: 11px;
  border: 1px solid var(--mi-line); background: var(--mi-surface);
}
.mech-res-item-ok    { /* neutral dark row — green accent on checkmark only */ }
.mech-res-item-issue { border-color: var(--mi-copper-ln); background: var(--mi-copper-bg); }
.mech-res-item-not_checked { opacity: .65; }
.mech-res-item-skipped_by_logic { border-color: rgba(99,140,185,.28); opacity: .80; }
.mech-res-item-skipped_by_logic .mech-res-item-state { color: #7eb3d3; }
.mech-res-item-row { display: flex; align-items: flex-start; gap: 10px; }
.mech-res-item-label { flex: 1; font-size: 14.5px; color: var(--mi-ink); line-height: 1.35; }
.mech-res-item-issue .mech-res-item-label { color: var(--mi-copper-ink); }
.mech-res-item-state { font-size: 16px; font-weight: 800; flex: none; margin-top: 1px; }
.mech-res-item-ok .mech-res-item-state    { color: var(--mi-ok); }
.mech-res-item-issue .mech-res-item-state { color: var(--mi-copper-ink); }
.mech-res-item-not_checked .mech-res-item-state { color: var(--mi-ink-faint); }
.mech-res-note { font-size: 13px; color: var(--mi-ink-soft); margin-top: 6px; font-style: italic; white-space: pre-line; }
/* T18-66B: multi-select defect list on the mechanic result view */
.mech-res-defects { margin-top: 6px; display: flex; flex-direction: column; gap: 4px; }
.mech-res-defect { font-size: 13px; color: var(--mi-ink-soft); }
.mech-res-photos { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.mech-res-photo-thumb { width: 70px; height: 70px; object-fit: cover; border-radius: 7px; border: 1px solid var(--mi-line); display: block; }

@media (max-width: 640px) {
  .mech-app { margin: -16px -14px; padding: 16px 14px 96px; } /* bottom clears fixed .mech-nav */
}

/* ── T18-B2: receptionist launch shell — brand link, warning banner, ─── */
/* ── table wrapper (Stage B2 cleanup, no new design system) ──────────── */

/* Root now repoints into the workspace via the brand logo — keep it looking
   like a logo, not a generic link. */
.brand:hover,
.brand:focus-visible {
  text-decoration: none;
}

/* Visible warning/error banner for the receptionist workspace (form
   validation errors, missing-template warnings, etc.). Uses the existing
   semantic warning tokens — no new palette. */
.warn {
  background: var(--gt-warning-bg);
  color: var(--gt-warning);
  border: 1px solid var(--gt-warning);
  border-radius: var(--gt-radius-sm);
  padding: 0.6rem 1rem;
  margin-bottom: 0.75rem;
  font-weight: 600;
  font-size: 0.9rem;
}

/* Horizontal scroll wrapper for wide inspection tables (active/completed
   lists) so they degrade gracefully on narrower desktop widths instead of
   overflowing the page. */
.table-wrap {
  overflow-x: auto;
  margin-bottom: 1rem;
}

/* ═══ Stage R2C — Receptionist Service Advisor Command Center ════════════ */
/* Desktop-first 3-zone workspace: command rail + operational board + context
   panel. All colors via .theme-light tokens (single source of truth); the few
   status hues below are semantic status tints, not a second palette. Calm-blue
   primary (var(--gt-accent)); GT red is logo-only. */

/* Wide canvas for data-dense screens (reception board, draft editor,
   template list — base.html adds .container-wide for those routes).
   Owner report (2026-07-22, 2K+ staff monitors): same min(vw, cap)
   auto-scaling as .container above, with a taller ceiling since these
   are genuinely data-dense grids/lists that benefit from more real width
   (more visible without scrolling), not just text that gets harder to
   read past a certain line length. */
.container-wide { max-width: none; }

/* ── Workspace top bar (role + live KPIs) ────────────────────────────── */
.rc-topbar {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 14px; margin-bottom: 18px;
}
.rc-topbar-eyebrow { display: block; font-size: 0.72rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--gt-accent); }
.rc-topbar-title { margin: 3px 0 0; font-size: 1.9rem; letter-spacing: -0.02em; color: var(--gt-text); }
.rc-topbar-stats { display: flex; gap: 8px; flex-wrap: wrap; }
.rc-kpi { display: inline-flex; align-items: baseline; gap: 5px; padding: 7px 13px; border-radius: 999px; background: var(--gt-surface); border: 1px solid var(--gt-border); font-size: 0.82rem; font-weight: 600; color: var(--gt-text-muted); box-shadow: var(--gt-shadow-sm); }
.rc-kpi b { font-size: 1rem; font-weight: 800; color: var(--gt-text); }
.rc-kpi-prog b { color: var(--gt-warning); }
.rc-kpi-done b { color: var(--gt-success); }

/* ── Alerts ───────────────────────────────────────────────────────────── */
.rc-alert { padding: 12px 16px; border-radius: var(--gt-radius-md); margin-bottom: 16px; font-weight: 600; font-size: 0.92rem; border: 1px solid transparent; }
.rc-alert-warn { background: var(--gt-warning-bg); color: var(--gt-warning); border-color: var(--gt-border); }
.rc-alert-ok { background: var(--gt-success-bg); color: var(--gt-success); border-color: var(--gt-border); }

/* ── 3-zone shell ────────────────────────────────────────────────────── */
/* R6H: 2-zone shell (rail + board). The former right-side "Текущий осмотр"
   context panel was removed (it duplicated the first row and implied a
   non-existent current selection); the board now takes the freed width. */
/* R6N-F: rail widened 288→364 + gap 22→30 so the creation block reads as a
   proportioned panel, not a cramped sidebar. The board column is minmax(0,1fr)
   and caps at 1180px (see .ro-board-head/.ro-list/.ro-done below), so
   the wider rail eats into what was previously unused gutter on wide screens
   rather than shrinking the card list. */
/* R6P-2: align-items changed start -> stretch, plus a min-height, so the
   board column genuinely fills the viewport on any real screen instead of a
   fixed row-count leaving a dead gap on taller/larger monitors than the one
   this was last measured on (owner-caught: "flexible, not a guessed magic
   number"). `.rc-rail`'s own sticky positioning is unaffected — stretching the
   grid cell only adds invisible empty cell space below its sticky content. */
/* Owner-approved Gate 1 reception ledger (2026-07-18): plain 2-column grid
   (create rail + full-width ledger) — no drawer, no 3rd reserved column,
   ever. Height retuned: the 103px offset predated the page-heading
   (.wo-list-header) added in an earlier stage, so .rc-shell's real top
   offset grew (measured 127.25px at both 1440x900 and 1786x1272 — the
   offset is viewport-width-independent, driven by stacked content height
   only) without this constant following — pushing .ro-pager below the
   viewport at both sizes. 148px leaves a real, measured safety margin
   (not just an exact fit) at both tested sizes; see the checker's own
   real-browser proof for the exact before/after numbers. */
.rc-shell { display: grid; grid-template-columns: 364px minmax(0, 1fr); gap: 30px; align-items: stretch; height: calc(100vh - 148px); min-height: 480px; }
.rc-rail, .rc-context { position: sticky; top: 18px; align-self: start; }

/* ── Command rail ────────────────────────────────────────────────────── */
.rc-cmd { background: var(--gt-surface); border: 1px solid var(--gt-border); border-radius: var(--gt-radius-lg); padding: 24px 22px; box-shadow: var(--gt-shadow-sm); }
.rc-cmd-head { display: flex; align-items: center; gap: 10px; margin-bottom: 18px; }
.rc-cmd-title { font-size: 1.34rem; font-weight: 800; color: var(--gt-text); }
.rc-cmd-step { margin: 4px 0 10px; font-size: 0.76rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--gt-accent); }
/* R6N-F: scoped scale-up for fields/inputs/buttons INSIDE the creation rail
   only. .rc-field/.rc-input/.rc-btn are shared with the detail-page VIN form
   and report buttons (reception_inspection_detail.html) — those must stay
   untouched, so every size bump here is scoped under .rc-cmd. */
.rc-cmd .rc-field { margin-bottom: 16px; }
.rc-cmd .rc-field label { font-size: 0.92rem; margin-bottom: 6px; }
.rc-cmd .rc-input, .rc-cmd .rc-select { min-height: 47px; font-size: 1rem; padding: 0.75rem 0.85rem; }
.rc-cmd .rc-btn:not(.rc-pick-btn) { min-height: 47px; font-size: 1rem; }
.rc-cmd .rc-btn.rc-btn-lg { min-height: 54px; font-size: 1.06rem; }
.rc-cmd .rcvp-hint { font-size: 0.82rem; line-height: 1.45; }
.rc-cmd .rc-or { margin: 16px 0; }

/* ── Forms / fields ──────────────────────────────────────────────────── */
.rc-form { margin: 0 0 4px; }
.rc-field { margin-bottom: 12px; }
.rc-field label { display: block; font-size: 0.8rem; font-weight: 600; color: var(--gt-text-muted); margin-bottom: 5px; }
.rc-input { width: 100%; box-sizing: border-box; padding: 0.58rem 0.8rem; border: 1px solid var(--gt-field-border); border-radius: 10px; font-size: 0.95rem; font-family: inherit; background: var(--gt-surface); color: var(--gt-text); transition: border-color .12s, box-shadow .12s; }
.rc-input:focus { outline: none; border-color: var(--gt-accent); box-shadow: 0 0 0 3px var(--gt-focus-ring); }
/* R6M: clean <select> — remove the raw native chrome (inconsistent with the
   polished client-search step) and draw one consistent custom caret. */
.rc-select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding-right: 2.2rem; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748B' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 0.75rem center; background-size: 1.05rem;
}
.rc-select::-ms-expand { display: none; }

/* R5: live client-search dropdown (progressive enhancement over the manual
   form below it) — an absolute overlay anchored to the search field. */
.rc-field-live { position: relative; }
/* R6I fix: the picklist carries the .rc-picklist class (display:flex), which
   overrode the [hidden] attribute's UA display:none (same specificity, declared
   later) — so the empty "hidden" list still rendered a 2px bordered bar right on
   top of the search button. Make [hidden] actually hide it. */
.rc-picklist[hidden], .rc-picklist-live[hidden] { display: none !important; }
.rc-picklist-live {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 20;
  margin: 0; padding: 4px; list-style: none;
  background: var(--gt-surface); border: 1px solid var(--gt-border);
  border-radius: var(--gt-radius-md); box-shadow: var(--gt-shadow-md);
  max-height: 260px; overflow-y: auto;
}
.rc-picklist-live .rc-pick { border: none; background: none; padding: 0; margin-bottom: 2px; }
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-FIDELITY-01: the matches stand INSIDE the «Новый осмотр» panel, under the
   number (accepted p05h), not as a layer hanging below the panel. */
.rc-phone-field .rc-picklist-live { position: static; margin-top: 8px; box-shadow: none; }
.rc-pick-live-link {
  display: flex; flex-direction: column; width: 100%; padding: 8px 10px;
  /* PATH09-OWNER-RECEPTION-ACCEPTANCE-CONSOLIDATED-CORRECTION-01: the row's corners follow the list's (14px card − 4px padding), and its hover is the module's one
     quiet fill — it was the full card radius inside a 6px padding, the odd corners the Owner saw on the make list. */
  border-radius: 10px; color: inherit;
  transition: background .1s;
}
.rc-pick-live-link:hover, .rc-pick-live-link:focus-visible { background: var(--gt-hover-quiet); }

/* ── Buttons ─────────────────────────────────────────────────────────── */
.rc-btn { display: inline-flex; align-items: center; justify-content: center; text-align: center; gap: 8px; min-height: 44px; padding: 0 1.25rem; border-radius: 14px; border: 1px solid transparent; font-size: 0.95rem; font-weight: 600; font-family: inherit; cursor: pointer; text-decoration: none; transition: background .14s, border-color .14s, box-shadow .14s, transform .06s; }
.rc-btn:active { transform: translateY(1px); }
/* Owner-approved flat deep-blue primary treatment (2026-07-17, resolves
   deferred item 140) — replaces the prior gradient. Reuses the SAME
   already-accepted, deliberately theme-neutral solid-primary token
   DS-1F introduced for exactly this "solid fill + near-white text"
   pattern (--gt-solid-accent-bg, already used by .btn.primary/
   .quick-btn) — no new token, no token value change. Text stays
   --gt-cta-solid-fg (existing, theme-neutral, #F5FAFD), which clears
   4.5:1 against this fill in BOTH themes since the fill itself no
   longer theme-switches (was the .rc-btn-primary-specific defect
   logged as deferred item 140 — a fixed gradient stop paired with a theme-switching
   bottom stop). */
.rc-btn-primary {
  color: var(--gt-cta-solid-fg);
  background: var(--gt-solid-accent-bg);
  border-color: rgba(18, 66, 100, .55);
  box-shadow: 0 6px 16px rgba(27, 94, 140, .30), inset 0 1px 0 rgba(255, 255, 255, .16);
}
.rc-btn-primary:hover { background: var(--gt-solid-accent-bg-hover); box-shadow: 0 9px 22px rgba(27, 94, 140, .38), inset 0 1px 0 rgba(255, 255, 255, .16); }
.rc-btn-primary:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--gt-focus-ring); }
.rc-btn-ghost { background: var(--gt-surface); color: var(--gt-accent); border-color: var(--gt-field-border); }
.rc-btn-ghost:hover { border-color: var(--gt-accent); background: var(--gt-accent-soft); }
.rc-btn-block { width: 100%; }
.rc-btn-lg { min-height: 52px; font-size: 1.02rem; border-radius: 15px; }
.rc-pick-btn { min-height: 34px; padding: 0 0.85rem; }

/* ── Client/vehicle pick + chosen ────────────────────────────────────── */
.rc-picklist { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
.rc-pick { display: flex; align-items: center; gap: 10px; padding: 9px 11px; border: 1px solid var(--gt-border); border-radius: var(--gt-radius-md); background: var(--gt-surface-muted); }
.rc-pick-txt { display: flex; flex-direction: column; min-width: 0; }
.rc-pick-main { font-weight: 600; font-size: 0.9rem; }
.rc-pick-sub { color: var(--gt-text-muted); font-size: 0.82rem; }
.rc-pick-btn { margin-left: auto; padding: 0.35rem 0.8rem; font-size: 0.83rem; }
/* R6L: "＋ Новый …" is a proper button (summary carries .rc-btn classes). */
.rc-new { margin: 0; }
.rc-new > summary { cursor: pointer; list-style: none; }
.rc-new > summary::-webkit-details-marker { display: none; }
.rc-new[open] > summary { margin-bottom: 12px; }
.rc-new-form { padding: 2px; }
/* R6M: instructive note when the client has no vehicle on file (the only path
   is to add one — no "или" redundancy). */
.rc-field-note { margin: 2px 0 12px; font-size: 0.85rem; color: var(--gt-text-muted); }
/* R6M: searchable make/model combobox. */
.rc-vehicle-picker { display: block; }
.rcvp-combo { position: relative; }
/* PATH09-OWNER-RECEPTION-ACCEPTANCE-CONSOLIDATED-CORRECTION-01: the Owner (2026-10-06) — the make list's names did not sit where the field's text sits, its hover
   fill was too loud and its corners odd. A row is now the field's own size, its name starts exactly where the typed
   text starts (list border 1px + padding 4px + row padding 0.85rem − 4px = the field's 1px + 0.85rem), the hover is
   the module's one quiet neutral fill (`--gt-hover-quiet`, also the row the arrow keys reached), and the row corners
   follow the card's (14 − 4 = 10px). */
.rcvp-list {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 30;
  margin: 0; padding: 4px; list-style: none; max-height: 260px; overflow-y: auto;
  border: 1px solid var(--gt-border); border-radius: 14px;
  background: var(--gt-surface); box-shadow: var(--gt-shadow-md);
}
.rcvp-opt {
  display: flex; align-items: center; min-height: 44px; box-sizing: border-box;
  padding: 8px calc(0.85rem - 4px); border-radius: 10px; font-size: 0.95rem; line-height: 1.3;
  color: var(--gt-text); cursor: pointer;
}
.rc-cmd .rcvp-opt { font-size: 1rem; }
.rcvp-opt:hover, .rcvp-opt.is-active { background: var(--gt-hover-quiet); }
.rcvp-opt-ext { color: var(--gt-text-muted); }
.rcvp-opt-add { color: var(--gt-accent); font-weight: 600; margin-top: 2px; box-shadow: inset 0 1px 0 var(--gt-border); border-radius: 0 0 10px 10px; }
.rcvp-hint { margin: 2px 0 10px; font-size: 0.78rem; color: var(--gt-text-muted); line-height: 1.4; }
/* R6M: secondary "＋ Другой автомобиль" — a quiet text toggle under the primary
   create form (not a full ghost button competing with "Создать осмотр"). */
.rc-new-secondary { margin-top: 12px; }
.rc-change-more { font-size: 0.85rem; font-weight: 600; color: var(--gt-accent); cursor: pointer; }
.rc-new-secondary[open] > summary { margin-bottom: 12px; }
.rc-muted { color: var(--gt-text-muted); font-size: 0.88rem; margin: 8px 0; }

/* R6L: "или" divider between "find existing" and "create new". */
.rc-or { display: flex; align-items: center; text-align: center; color: var(--gt-text-muted); font-size: 0.8rem; margin: 12px 0; }
.rc-or::before, .rc-or::after { content: ""; flex: 1; height: 1px; background: var(--gt-border); }
.rc-or span { padding: 0 10px; }

/* R6L: step indicator (Клиент → Автомобиль → Параметры). */
/* R6M: the .rc-steps ①②③ step indicator was removed (§16.6 — signposting steps
   instead of collapsing them). Its CSS is deleted as dead code. */

/* R6L: chosen client/vehicle card — badge + Сменить on top, name full width
   below (fixes the awkward 3-line name wrap). */
.rc-chosen { display: flex; flex-direction: column; padding: 11px 13px; margin-bottom: 13px; border: 1px solid var(--gt-border); border-left: 3px solid var(--gt-accent); border-radius: var(--gt-radius-md); background: var(--gt-surface-muted); }
.rc-chosen-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 5px; }
.rc-chosen-badge { font-size: 0.64rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--gt-accent); background: var(--gt-accent-soft); border-radius: 6px; padding: 3px 7px; }
.rc-chosen-main { font-weight: 700; font-size: 0.92rem; overflow-wrap: anywhere; }
.rc-chosen-sub { font-size: 0.8rem; color: var(--gt-text-muted); overflow-wrap: anywhere; }
.rc-change { flex: none; font-size: 0.82rem; font-weight: 600; color: var(--gt-text-muted); text-decoration: none; }
.rc-change:hover { color: var(--gt-accent); }

/* ── Operational board ───────────────────────────────────────────────── */
.rc-board-head { display: flex; align-items: center; gap: 10px; margin: 0 0 14px; }
.rc-board-title { margin: 0; font-size: 1.3rem; font-weight: 800; letter-spacing: -0.01em; color: var(--gt-text); }
.rc-count { display: inline-flex; align-items: center; justify-content: center; min-width: 26px; height: 24px; padding: 0 9px; border-radius: 12px; background: var(--gt-accent-soft); color: var(--gt-accent); font-size: 0.84rem; font-weight: 800; }
.rc-count-muted { background: var(--gt-surface-2); color: var(--gt-text-muted); }

/* ── Task rows (operational queue, not a table/card dump) ────────────── */
.rc-queue { display: flex; flex-direction: column; gap: 10px; }
.rc-task { position: relative; display: flex; align-items: center; gap: 12px; overflow: hidden; padding: 14px 16px 14px 0; border: 1px solid var(--gt-border); border-radius: var(--gt-radius-lg); background: var(--gt-surface); box-shadow: var(--gt-shadow-sm); text-decoration: none; color: inherit; transition: border-color .12s, box-shadow .12s; }
.rc-task:hover { border-color: var(--gt-accent); box-shadow: var(--gt-shadow-md); }
.rc-task:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--gt-focus-ring); }
.rc-task.is-current { border-color: var(--gt-accent); box-shadow: 0 0 0 1px var(--gt-accent) inset, var(--gt-shadow-sm); }
.rc-task-accent { flex: none; width: 5px; align-self: stretch; background: var(--gt-border); }
.rc-task-draft .rc-task-accent { background: var(--gt-status-draft-accent); }
.rc-task-in_progress .rc-task-accent { background: var(--gt-warning); }
.rc-task-completed .rc-task-accent { background: var(--gt-success); }
.rc-task-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; padding-left: 14px; }
.rc-task-line1 { display: flex; align-items: center; gap: 10px; }
.rc-task-client { font-weight: 800; font-size: 1.02rem; color: var(--gt-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rc-task-line2 { display: flex; align-items: center; gap: 6px; color: var(--gt-text-muted); font-size: 0.88rem; }
.rc-task-mech { color: var(--gt-text-muted); }
.rc-mini-ic { width: 15px; height: 15px; flex: none; }
.rc-task-progline { display: flex; align-items: center; gap: 10px; }
.rc-task-open { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; margin-right: 12px; border-radius: 8px; color: var(--gt-text-muted); background: var(--gt-surface-muted); }
.rc-task:hover .rc-task-open { color: var(--gt-accent); background: var(--gt-accent-soft); }
.rc-task-open svg { width: 17px; height: 17px; }
.rc-task-completed { background: var(--gt-surface-muted); }
.rc-task-sm { padding-top: 11px; padding-bottom: 11px; }
.rc-task-sm .rc-task-client { font-size: 0.95rem; }

/* ── Completed block (de-emphasized, collapsible) ────────────────────── */
.rc-done-block { margin-top: 24px; }
.rc-done-summary { display: flex; align-items: center; gap: 9px; cursor: pointer; font-size: 1.05rem; font-weight: 700; color: var(--gt-text-muted); list-style: none; padding: 6px 0; }
.rc-done-summary::-webkit-details-marker { display: none; }
.rc-done-summary::before { content: "\25B8"; color: var(--gt-text-muted); transition: transform .12s; display: inline-block; }
.rc-done-block[open] .rc-done-summary::before { transform: rotate(90deg); }
.rc-queue-done { margin-top: 10px; }
.rc-done-empty { padding: 4px 0 0; }

/* ── Status chips ────────────────────────────────────────────────────── */
.rc-chip { display: inline-flex; align-items: center; padding: 3px 11px; border-radius: 999px; font-size: 0.78rem; font-weight: 700; white-space: nowrap; }
.rc-chip-draft { background: var(--gt-status-draft-chip-bg); color: var(--gt-status-draft-chip-fg); }
.rc-chip-in_progress { background: var(--gt-warning-bg); color: var(--gt-warning); }
.rc-chip-completed { background: var(--gt-success-bg); color: var(--gt-success); }
.rc-chip-cancelled { background: var(--gt-danger-bg); color: var(--gt-danger); }
/* R6Q-1: annulled uses a distinct muted slate-purple (the same neutral "voided"
   tone as Н/П), so it reads as a different inactive state from red 'cancelled'. */
.rc-chip-annulled { background: var(--gt-status-admin-chip-bg); color: var(--gt-status-admin-chip-fg); }
/* R6U: paused reuses the same slate-purple "administrative note" tone as
   annulled — it is not itself a status (the real chip next to it still reads
   "В работе"), just a read-only sub-badge that this osmotr is on hold. */
.rc-chip-paused { background: var(--gt-status-admin-chip-bg); color: var(--gt-status-admin-chip-fg); }
/* An unrecognised status, on the detail page and the results screen. */
.rc-chip-unknown { background: var(--gt-warning-bg); color: var(--gt-warning); }
.rc-chip-lg { font-size: 0.86rem; padding: 4px 13px; }
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-01: «PDF скачан» — the recorded handover of the client's document.
   It is the accent tone, not a success or a warning: it is the act that finishes the work, and it stands
   beside the status chip with the moment and the person in quiet text after it. */
.rc-chip-pdf { background: var(--gt-accent-soft); color: var(--gt-accent); }
.rc-pdf-fact { font-size: 0.86rem; color: var(--gt-text-muted); align-self: center; }
.ro-tag-pdf { background: var(--gt-accent-soft); color: var(--gt-accent); }
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-01: ONE TAP, not a dropdown. The cars a client has and the mechanics
   who can take the work are short lists the receptionist reads at a glance; opening a <select> to choose
   between two of them is two actions where one does. The chosen one is obvious without colour alone: it
   carries the accent border AND the filled radio. */
.rc-pickone { display: flex; flex-wrap: wrap; gap: 8px; }
.rc-pickone-opt { display: inline-flex; align-items: baseline; gap: 8px; padding: 9px 14px; border-radius: 10px;
  border: 1px solid var(--gt-border); background: var(--gt-surface); cursor: pointer; min-height: 40px; }
.rc-pickone-opt:hover { border-color: var(--gt-accent); }
.rc-pickone-opt:focus-within { outline: 2px solid var(--gt-focus-ring); outline-offset: 2px; }
.rc-pickone-opt input { accent-color: var(--gt-accent); margin: 0; }
.rc-pickone-opt:has(input:checked) { border-color: var(--gt-accent); background: var(--gt-accent-soft); }
.rc-pickone-main { font-weight: 600; color: var(--gt-text); }
.rc-pickone-sub { font-size: 0.82rem; color: var(--gt-text-muted); }
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-FIDELITY-01 (2026-09-23): the one «Новый осмотр» form as accepted
   (p05h–p05j, p02). An option is a full-width row with its dot on the left — `.rc-field label {display:block}`
   used to win over the option's own flex and stacked the dot above the name. A refusal is a red line under
   its field and a red edge on the field itself. */
.rc-cmd .rc-pickone { flex-direction: column; flex-wrap: nowrap; }
.rc-field .rc-pickone-opt, .rc-pickone-opt { display: flex; flex-wrap: wrap; align-items: center; column-gap: 10px; row-gap: 2px; margin: 0; font-size: 0.95rem; font-weight: 400; color: var(--gt-text); border: 1px solid var(--gt-field-border); background: var(--gt-surface); }
.rc-pickone-opt .rc-pickone-sub { flex-basis: 100%; padding-left: 23px; }
.rc-pickone-opt input { width: auto; flex: none; min-height: 0; }
.rc-cmd [hidden] { display: none !important; }
.rc-sub, .rc-cmd .rc-phone-field > label { display: block; margin: 4px 0 8px; font-size: 0.74rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--gt-text-muted); }
.rc-field-err { margin: 6px 0 0; font-size: 0.85rem; font-weight: 600; color: var(--gt-danger); }
.rc-input.is-bad, .rc-select.is-bad, .rc-pickone.is-bad .rc-pickone-opt { border-color: var(--gt-danger); box-shadow: 0 0 0 1px var(--gt-danger); }
.rc-newcar-toggle { display: inline-block; margin-top: 10px; padding: 0; background: none; border: 0; font-family: inherit; }
.rc-newcar { margin-top: 12px; }
.rc-one .rc-btn-lg { margin-top: 6px; }
.rc-cmd .rc-btn-primary[disabled] { opacity: 1; background: var(--gt-surface-2); color: var(--gt-text-muted); box-shadow: none; cursor: not-allowed; }
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-01: the row this board has just created. The mark is the accent edge and
   a soft ground — never colour alone: the line above the board names the same inspection by its number. */
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-FIDELITY-01: the row the press created is marked (accepted p05b) — as
   `.ro-row.ro-row-new`, because the later `.ro-row` rules used to win and the mark never showed. */
.ro-row.ro-row-new { border-color: var(--gt-accent); background: var(--gt-accent-soft); box-shadow: inset 4px 0 0 0 var(--gt-accent); }
/* PATH08-RECEPTION-VISUAL-CONSOLIDATED-CLOSURE-01: on that soft ground the row's quiet grey («VIN не указан», the
   phone, «Осмотр №N», 12.8 px) was 3.63:1 in the dark desk (4.84:1 light), measured at 2560x1440. Inside the marked row
   it reads as the theme's muted text: 5.90:1 dark, 5.08:1 light. The mark itself is unchanged. */
.ro-row.ro-row-new { --gt-text-soft: var(--gt-text-muted); }
.rc-created { display: flex; align-items: center; gap: 14px; }
/* The short message at the bottom right (accepted p05b), not a strip across the board. */
.rc-created.rc-toast { position: fixed; right: 32px; bottom: 32px; z-index: 60; padding: 14px 18px; border-radius: 12px;
  background: var(--gt-surface); border: 1px solid var(--gt-field-border); box-shadow: var(--gt-shadow-md);
  font-size: 16px; color: var(--gt-text); }
.rc-toast-ic { flex: none; color: var(--gt-success); }
.rc-created-open { font-weight: 600; color: var(--gt-accent); text-decoration: none; }
.rc-created-open:hover, .rc-created-open:focus-visible { text-decoration: none; color: var(--gt-accent-hover, var(--gt-accent)); } /* PATH09-OWNER-RECEPTION-ACCEPTANCE-CONSOLIDATED-CORRECTION-01: no underline */

/* ── Tags ────────────────────────────────────────────────────────────── */
.rc-tag { display: inline-flex; align-items: center; padding: 2px 9px; border-radius: 7px; font-size: 0.78rem; font-weight: 600; background: var(--gt-surface-2); color: var(--gt-text); }
.rc-tag-issue { background: var(--gt-danger-bg); color: var(--gt-danger); }
.rc-tag-ok { background: var(--gt-success-bg); color: var(--gt-success); }

/* ── Progress bar ────────────────────────────────────────────────────── */
.rc-prog { display: inline-block; width: 120px; height: 7px; border-radius: 999px; background: var(--gt-surface-2); overflow: hidden; vertical-align: middle; }
.rc-prog-fill { display: block; height: 100%; border-radius: 999px; background: var(--gt-accent); transition: width .28s; }
.rc-prog-lbl { font-size: 0.8rem; font-weight: 600; color: var(--gt-text-muted); }
.rc-prog-lg { width: 100%; height: 10px; }

/* ── Empty states ────────────────────────────────────────────────────── */
.rc-empty { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 46px 26px; text-align: center; color: var(--gt-text-muted); border: 1px dashed var(--gt-border); border-radius: var(--gt-radius-lg); background: var(--gt-surface); }
.rc-empty p { margin: 0; }
.rc-empty-ic { width: 42px; height: 42px; color: var(--gt-border); }

/* ── Right context panel ─────────────────────────────────────────────── */
.rc-ctx-card { position: relative; display: flex; overflow: hidden; border: 1px solid var(--gt-border); border-radius: var(--gt-radius-lg); background: var(--gt-surface); box-shadow: var(--gt-shadow-md); }
.rc-ctx-accent { flex: none; width: 5px; align-self: stretch; background: var(--gt-border); }
.rc-task-in_progress.rc-ctx-card .rc-ctx-accent { background: var(--gt-warning); }
.rc-task-draft.rc-ctx-card .rc-ctx-accent { background: var(--gt-status-draft-accent); }
.rc-task-completed.rc-ctx-card .rc-ctx-accent { background: var(--gt-success); }
.rc-ctx-body { flex: 1; min-width: 0; padding: 20px; }
.rc-ctx-eyebrow { display: block; font-size: 0.7rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--gt-text-muted); }
.rc-ctx-client { margin: 6px 0 3px; font-size: 1.28rem; font-weight: 800; letter-spacing: -0.01em; color: var(--gt-text); }
.rc-ctx-veh { margin: 0 0 12px; color: var(--gt-text-muted); font-size: 0.92rem; }
.rc-ctx-prog { display: flex; align-items: center; gap: 12px; margin: 16px 0; }
.rc-ctx-pct { flex: none; font-weight: 800; font-size: 1.02rem; color: var(--gt-accent); min-width: 42px; text-align: right; }
.rc-ctx-facts { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin: 0 0 18px; }
.rc-ctx-facts dt { font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--gt-text-muted); margin-bottom: 3px; }
.rc-ctx-facts dd { margin: 0; font-weight: 700; font-size: 0.94rem; color: var(--gt-text); }
.rc-ctx-empty { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 34px 22px; text-align: center; color: var(--gt-text-muted); border: 1px dashed var(--gt-border); border-radius: var(--gt-radius-lg); background: var(--gt-surface); }
.rc-ctx-empty svg { width: 36px; height: 36px; color: var(--gt-border); }
.rc-ctx-empty p { margin: 0; font-size: 0.9rem; }

/* ── Detail page (same workspace language) ───────────────────────────── */
.rc-back { display: inline-flex; align-items: center; gap: 6px; margin-bottom: 16px; font-weight: 700; font-size: 0.9rem; color: var(--gt-accent); text-decoration: none; }
.rc-back svg { width: 17px; height: 17px; }
/* R6K: hover affordance is the accent color, not an underline. */
.rc-back:hover, .rc-back:focus-visible { text-decoration: none; color: var(--gt-accent-hover); }
.rc-detail-hero { position: relative; display: flex; overflow: hidden; padding: 0; border: 1px solid var(--gt-border); border-radius: var(--gt-radius-lg); background: var(--gt-surface); box-shadow: var(--gt-shadow-sm); margin-bottom: 18px; }
.rc-detail-hero .rc-ctx-accent, .rc-detail-hero .rc-task-accent { width: 6px; }
.rc-detail-hero-body { flex: 1; min-width: 0; padding: 22px 26px; }
.rc-detail-hero-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 18px; }
/* PATH08-REUSABLE-VISUAL-ACCEPTANCE-AND-UI-CLOSURE-01: the state chips stay together at the right edge in every state. */
.rc-detail-hero-chips { display: inline-flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 8px; flex-shrink: 0; }
.rc-detail-eyebrow { display: inline-block; font-size: 0.72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--gt-text-muted); }
.rc-detail-title { margin: 5px 0 4px; font-size: 1.55rem; letter-spacing: -0.01em; color: var(--gt-text); }
.rc-detail-veh { margin: 0; color: var(--gt-text-muted); font-size: 0.98rem; }
/* R6B: internal preview-link action row under the report hero */
/* PATH08-RECEPTION-UI-COHERENCE-01: the state's ONE explanation and its ONE
   next step, directly under the chip that names it. The next step is the
   emphasised half -- it is the line a receptionist acts on -- and it is
   emphasised by weight and colour rather than by being a button, because for
   three of the five states the next move is not theirs to make. */
.rc-state { margin: 14px 0 0; display: flex; flex-direction: column; gap: 3px; max-width: 62ch; }
.rc-state-meaning { color: var(--gt-text-muted); font-size: 0.94rem; }
.rc-state-next { color: var(--gt-text); font-size: 0.96rem; font-weight: 600; }
.rc-detail-hero-actions { margin-top: 14px; display: flex; gap: 10px; flex-wrap: wrap; }

/* ── R6Q-1: inspection cancel / annul action + inactivation record ──────── */
/* The trigger expands (no JS, <details>) to a reason form.
   PATH08-RECEPTION-UI-COHERENCE-01: it was NOT low-key enough, and on two of
   the five states it was not competing with anything -- a draft and an
   in-progress inspection show no hero action at all, so a bordered pill in
   danger red was the loudest AND the only control on the page. It is a muted
   text control now: no border, no surface, no red until the pointer or the
   keyboard is actually on it. Separated from the content above it by a rule,
   so it reads as the footer of the card rather than as its call to action.
   The hit area is unchanged (the padding stays), and the expanded form and its
   solid danger confirm button are untouched -- the CONFIRMATION is where a
   destructive action is allowed to be loud. */
.rc-inact-wrap { margin-top: 22px; padding-top: 14px; border-top: 1px solid var(--gt-border); }
.rc-inact > summary.rc-inact-trigger {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer; user-select: none;
  padding: 8px 0; border-radius: 12px; border: 1px solid transparent;
  background: none; color: var(--gt-text-muted);
  font-size: 0.86rem; font-weight: 500; list-style: none;
}
.rc-inact > summary.rc-inact-trigger::-webkit-details-marker { display: none; }
.rc-inact > summary.rc-inact-trigger::before { content: "✕"; font-size: 0.85rem; }
.rc-inact > summary.rc-inact-trigger:hover,
.rc-inact > summary.rc-inact-trigger:focus-visible { color: var(--gt-danger); text-decoration: none; }
/* PATH09-OWNER-RECEPTION-ACCEPTANCE-CONSOLIDATED-CORRECTION-01: no underline — a control of this module never underlines itself (the R5/R6P-2 rule above; the Owner,
   2026-10-06: «подчеркивание снизу идет»). The colour still turns danger; a keyboard reaching it sees a ring. */
.rc-inact > summary.rc-inact-trigger:focus-visible { outline: 2px solid var(--gt-accent); outline-offset: 4px; border-radius: 6px; }
.rc-inact-need { font-weight: 500; color: var(--gt-text-muted); }
.rc-inact[open] > summary.rc-inact-trigger { color: var(--gt-danger); font-weight: 600; }
.rc-inact-form {
  margin-top: 10px; max-width: 420px; padding: 16px; border: 1px solid var(--gt-border);
  border-radius: var(--gt-radius-md); background: var(--gt-surface-muted);
  display: flex; flex-direction: column; gap: 12px;
}
.rc-inact-title { margin: 0; font-weight: 700; color: var(--gt-text); font-size: 0.98rem; }
.rc-inact-comment { resize: vertical; min-height: 44px; font: inherit; }
.rc-field-opt { font-weight: 400; color: var(--gt-text-muted); font-size: 0.82rem; }
.rc-inact-submit { align-self: flex-start; }
/* Danger button (solid) — only used to confirm cancel/annul. */
.rc-btn-danger { background: var(--gt-danger); color: var(--gt-danger-solid-fg); border-color: var(--gt-danger); }
.rc-btn-danger:hover { filter: brightness(1.05); }

/* Factual inactivation record on an already-cancelled/annulled inspection —
   neutral, records who/when/why; never labels it "bad work". */
.rc-inact-record {
  display: flex; align-items: flex-start; gap: 10px; padding: 13px 16px;
  border-radius: var(--gt-radius-md); border: 1px solid var(--gt-border);
  background: var(--gt-surface-muted); color: var(--gt-text-muted);
}
.rc-inact-record svg { width: 20px; height: 20px; flex: none; margin-top: 1px; }
.rc-inact-record-cancelled { color: var(--gt-danger); }
.rc-inact-record-annulled { color: var(--gt-status-admin-chip-fg); }
.rc-inact-record-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rc-inact-record-title { font-weight: 700; }
.rc-inact-record-meta { font-size: 0.86rem; color: var(--gt-text-muted); }
.rc-inact-record-comment { font-size: 0.88rem; color: var(--gt-text); overflow-wrap: anywhere; }

.rc-card { background: var(--gt-surface); border: 1px solid var(--gt-border); border-radius: var(--gt-radius-lg); padding: 22px; box-shadow: var(--gt-shadow-sm); margin-bottom: 18px; }
.rc-card-head { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
.rc-card-ic { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 9px; background: var(--gt-accent-soft); color: var(--gt-accent); }
.rc-card-ic svg { width: 19px; height: 19px; }
.rc-card-title { margin: 0; font-size: 1.12rem; font-weight: 700; color: var(--gt-text); }
.rc-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 16px 20px; margin: 0; padding-top: 18px; border-top: 1px solid var(--gt-border); }
.rc-fact { margin: 0; }
.rc-fact dt { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--gt-text-muted); margin-bottom: 4px; }
.rc-fact dd { margin: 0; font-weight: 700; color: var(--gt-text); font-size: 0.96rem; }
.rc-detail-prog { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; }
/* Lifecycle completion (2026-07-19): truthful pre-start state on the
   reception detail card — replaces the "0% / 0-of-N" fraction shown before
   a mechanic has taken the inspection. Theme-aware via the same existing
   tokens the surrounding card already uses. */
.rc-notstarted { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; padding: 14px 16px; margin-bottom: 18px; border-radius: var(--gt-radius-md); background: var(--gt-surface-muted); border: 1px solid var(--gt-border); }
.rc-notstarted p { margin: 0; }
.rc-prog-pct { flex: none; font-weight: 800; font-size: 1.05rem; color: var(--gt-accent); min-width: 46px; text-align: right; }
.rc-metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 12px; margin-bottom: 18px; }
.rc-metric { padding: 14px 16px; border-radius: var(--gt-radius-md); background: var(--gt-surface-muted); border: 1px solid var(--gt-border); text-align: center; }
.rc-metric-num { display: block; font-size: 1.4rem; font-weight: 800; color: var(--gt-text); line-height: 1; }
.rc-metric-lbl { display: block; margin-top: 6px; font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; color: var(--gt-text-muted); }
/* PATH08-INSPECTION-PROGRESS-COHERENCE-01: a fault count of ZERO is the best
   outcome an inspection can have, and it was painted in the danger colour --
   the same red as «7 замечаний» -- so a clean car and a car with seven faults
   were told apart only by reading the digit. Zero now reads as the success it
   is; the danger colour is kept for a count that is actually non-zero. */
.rc-metric-issue .rc-metric-num { color: var(--gt-danger); }
.rc-metric-issue.rc-metric-zero .rc-metric-num { color: var(--gt-success); }
.rc-metric-wait .rc-metric-num { color: var(--gt-text-muted); }
/* The three lanes that appear only when they are not zero. «Не применимо» is
   the mechanic's own decision (the slate-purple «administrative note» tone the
   annulled chip and the paused badge already use), «Не отвечено» is work still
   owed (warning), «Пропущено автоматически» is the template's own skip and is
   deliberately the quietest of the three -- nobody has to do anything about it. */
.rc-metric-na .rc-metric-num { color: var(--gt-status-admin-chip-fg); }
.rc-metric-open .rc-metric-num { color: var(--gt-warning); }
.rc-metric-muted .rc-metric-num { color: var(--gt-text-muted); }
.rc-metric-muted .rc-metric-lbl { color: var(--gt-text-soft); }
.rc-detail-actions { margin-top: 2px; }
.rc-inprogress-note { display: flex; align-items: center; gap: 10px; padding: 13px 16px; border-radius: var(--gt-radius-md); background: var(--gt-warning-bg); border: 1px solid var(--gt-border); color: var(--gt-warning); font-weight: 600; font-size: 0.92rem; }
.rc-inprogress-note svg { width: 20px; height: 20px; flex: none; }

/* ── Responsive ──────────────────────────────────────────────────────── */
@media (max-width: 1360px) {
  .rc-shell { grid-template-columns: 260px minmax(0, 1fr); gap: 18px; }
}
/* PATH08-RECEPTION-RESPONSIVE-BOARD-01 (2026-09-02): the single-column
   breakpoint moves 820 -> 1000, and the shell stops being a fixed-height box
   once it is stacked. Both are the same measured defect.

   (a) WIDTH. Below 1201 the shell was still two columns, so the board got
   `viewport - 88 rail - 56 page padding - 260 create rail - 18 gap` — 398px
   at 900 CSS px and 602px at 1024. Measured at 900: `.ro-body` 48px wide,
   `.ro-side` and the `.ro-open` chevron rendered past the right edge of the
   viewport and cut off by `.ro-row`'s own `overflow: hidden`. The board is
   the work on this screen and the create panel is a tool beside it; once the
   split starves the board, the tool belongs above it and the board takes the
   full width. 1200 is a MEASURED boundary, chosen as low as the evidence
   allows so the board keeps its place beside the panel wherever it still
   works: at 1201 the two-column board is 763px, and the densest real row
   still fits it with nothing clipped and nothing off-viewport (verified at
   1201, 1240 and 1280). 1280 CSS px is what a 2560x1440 monitor becomes at
   200% browser zoom, and it stays the accepted two-column layout there.

   (b) HEIGHT. `height: calc(100vh - 148px)` with `min-height: 480px` is a
   two-COLUMN assumption: side by side, rail and board each get the full
   height. Stacked, they have to share it — at 360x780 that left `.ro-list`
   73px, one visible row, with the rest reachable only inside the list's own
   scroller. At 200% browser zoom on a 1440x900 screen (720x450 CSS px) the
   480px floor is taller than the viewport itself. Stacked, the page scrolls
   and the list is simply as tall as its rows: `overflow-y: visible` also
   removes the horizontal scroller the `auto` value silently implied. */
@media (max-width: 1200px) {
  .rc-shell { grid-template-columns: 1fr; height: auto; min-height: 0; }
  .rc-rail { position: static; }
  .ro-board { min-height: 0; }
  .ro-list { overflow-y: visible; }
}
@media (prefers-reduced-motion: reduce) {
  .rc-task, .rc-btn, .rc-prog-fill, .rc-done-summary::before { transition: none; }
}
/* ═══ end Stage R2C ══════════════════════════════════════════════════════ */
/* ═══ Stage R2D — Inspection Operations Workspace (situation rows) ═══════ */
/* Wide situation rows (vehicle-first), status filters, compact process
   timeline, prominent "requires decision" signal. Colors via .theme-light
   tokens; deep blue-teal primary; GT red never a primary action fill. */

/* R6P-2: flex column so the row list (not the search bar/filters/pager) is
   the ONE part that grows/shrinks to absorb whatever vertical space this
   real screen actually has. */
.ro-board { min-width: 0; display: flex; flex-direction: column; min-height: 0; }
.ro-board-head, .ro-pager { flex: none; }
/* Reception toolbar redesign (2026-07-22, equal-hierarchy correction):
   search is one of three same-weight filter groups now (Поиск/Статус/
   Период), not a separate, larger, standalone row — same 36px control
   height and same font-size as .ro-status-select, so nothing here reads
   as "more important" than the others by sheer size. */
.ro-search { display: flex; align-items: center; gap: 10px; width: 100%; position: relative; }
.ro-search-ic { position: absolute; left: 14px; width: 16px; height: 16px; color: var(--gt-text-muted); pointer-events: none; }
.ro-search-input {
  flex: 1; min-width: 0; height: 36px; padding: 0 40px 0 38px; border: 1px solid var(--gt-field-border);
  border-radius: var(--gt-radius-md); font: inherit; font-size: 0.88rem; color: var(--gt-text); background: var(--gt-surface);
}
.ro-search-input:focus { outline: none; border-color: var(--gt-accent); box-shadow: 0 0 0 3px var(--gt-focus-ring); }
.ro-search-clear {
  /* Reception toolbar redesign (2026-07-22): right offset was 92px to clear
     the now-removed "Найти" button; with no button (and a shorter, equal-
     weight input), the clear icon sits close to the input's own edge. */
  position: absolute; right: 8px; width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; color: var(--gt-text-muted); text-decoration: none; font-size: 0.85rem;
}
.ro-search-clear:hover { background: var(--gt-surface-2); color: var(--gt-text); }
/* R6P-2: pager — 10 per page; the list flexes to fill real screen height. */
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-01, accepted 2026-09-19: «внизу справа „1–10 из 15“ и две
   стрелки». Right, not centred: the list is read from the left, and the control that moves it belongs
   at the end of that reading, not in the middle of the page. The two buttons are square (38px, above
   the touch floor) because an arrow has no text to set their width. */
.ro-pager { display: flex; align-items: center; justify-content: flex-end; gap: 10px; max-width: min(94vw, 1600px); margin: 4px auto 2px; padding-right: 26px; }
.ro-pager-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: var(--gt-radius-md);
  border: 1px solid var(--gt-border); background: var(--gt-surface); color: var(--gt-text);
  text-decoration: none; transition: border-color .12s, background .12s;
}
.ro-pager-btn svg { width: 18px; height: 18px; }
.ro-pager-btn:hover { border-color: var(--gt-accent); background: var(--gt-accent-soft); }
/* An unavailable arrow stays visible and stays in place — a control that disappears at the edge of a
   list moves the one beside it under the finger that was aiming at it. */
.ro-pager-btn.is-disabled { color: var(--gt-text-soft); background: var(--gt-surface-muted); border-color: var(--gt-border); pointer-events: none; opacity: .35; }
.ro-pager-info { margin-right: 6px; font-size: 0.9rem; font-weight: 600; color: var(--gt-text-muted); font-variant-numeric: tabular-nums; }

.ro-board-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px; margin-bottom: 6px; }

/* Six-counterexamples correction (2026-07-22): visible caption stacked
   above each filter row (was aria-label only — invisible to sighted
   users, no on-screen cue distinguishing "Статус" from "Период"). */
.ro-filter-group { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; min-width: 0; max-width: 100%; }
.ro-filter-group-label { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--gt-text-soft); }
/* Reception toolbar redesign (2026-07-22, equal-hierarchy correction): only
   the search group grows to fill the row's free space (a search box that
   never grows would look arbitrarily narrow) — Статус/Период stay their
   natural content width, same as any other filter control. */
.ro-filter-group-grow { flex: 1 1 260px; min-width: 0; align-items: stretch; }
.ro-filter-group-grow .ro-search { max-width: 480px; }

/* ── Status filter (reception toolbar redesign, 2026-07-22, variant 2) ──
   Replaces the old pill row (.ro-filters/.ro-filter/.ro-filter-n/
   .ro-filter-decide, retired — status now changes via one dropdown, no
   per-status pill styling to carry forward).

   PATH08-RECEPTION-RESPONSIVE-BOARD-01 (2026-09-02), PRODUCT defect found
   while delivering the responsive board and repaired here because it sits in
   this delivery's own path and silently disabled a rule this delivery edits:
   this comment used to end with Jinja's `#}` instead of a CSS comment
   terminator, so it never closed. Introduced 2026-07-22 in `b0e73b07` — the
   very commit that authored the rule below — it swallowed both
   `.ro-status-select` blocks whole
   — for 42 days the Статус dropdown on this board has rendered as an
   unstyled native control (measured 180x39 against the 190x36 written here),
   next to a Поиск field the same 2026-07-22 redesign gave the matching
   height and border precisely so neither would read as the more important of
   the two. Closing the comment applies the rule its own author wrote. */
.ro-status-select {
  height: 36px; padding: 0 10px; border-radius: var(--gt-radius-md);
  border: 1px solid var(--gt-field-border); background: var(--gt-surface); color: var(--gt-text);
  /* PATH08-RECEPTION-RESPONSIVE-BOARD-01: was `min-width: 190px`, which a
     narrow board could not honour and could not override (min-width beats
     max-width in the cascade of used values). Expressed as a preferred width
     with a real ceiling instead, so the control keeps its accepted desktop
     size and still fits a 360px screen. */
  /* PATH08-REUSABLE-VISUAL-ACCEPTANCE-AND-UI-CLOSURE-01: no `font-weight` of its own. Measured on the 2560x1440
     workstation in both themes, «Статус» printed its value at 600 beside «Поиск» typing at 400 — two fields of
     one toolbar set in two weights, the unequal-neighbour defect this redesign existed to remove. */
  font: inherit; font-size: 0.88rem; width: 190px; min-width: 0; max-width: 100%; cursor: pointer;
}
.ro-status-select:focus { outline: none; border-color: var(--gt-accent); box-shadow: 0 0 0 3px var(--gt-focus-ring); }
/* PATH09-OWNER-RECEPTION-ACCEPTANCE-CONSOLIDATED-CORRECTION-01: «Статус» draws the same caret as every other select of the module (`.rc-select`); it had none. */
.ro-status-select {
  padding: 0 2.4rem 0 12px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748B' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 0.8rem center; background-size: 1.05rem;
}
/* PATH08-REUSABLE-VISUAL-ACCEPTANCE-AND-UI-CLOSURE-01: a placeholder is words a person reads to know what a field
   takes. None declared a colour, so the browser's own #757575 painted «Клиент, телефон, авто или VIN» at 3.56:1 on
   the dark field and 4.47:1 on the light one. Each desktop theme reads it as its own muted text. */
.theme-light ::placeholder,
.theme-dark-desktop ::placeholder { color: var(--gt-text-muted); opacity: 1; }

/* Live search debounce indicator (reception toolbar redesign, 2026-07-22):
   right offset clears the clear-icon's own slot so the two never overlap. */
.ro-search-status { position: absolute; right: 34px; color: var(--gt-text-muted); font-size: 0.78rem; pointer-events: none; }
/* .ro-count retired (owner correction, 2026-07-22): the result-count label
   was removed from the toolbar entirely. */
/* R6L: date-period filter chips (by creation date), right of the board head. */
/* Reception toolbar redesign (2026-07-22): margin-left:auto pushes the
   whole tools block (period + count) flush to the row's right edge,
   instead of flex-grow expanding it into the empty middle and leaving
   Период to render right next to Статус on the left. */
.ro-board-tools { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-left: auto; min-width: 0; max-width: 100%; }
/* PATH08-RECEPTION-RESPONSIVE-BOARD-01: the preset chip row was a rigid
   inline-flex of `white-space: nowrap` pills — a fixed 277px block inside a
   board only 244px wide at 360 CSS px. It was the one element that produced
   real horizontal PAGE scrolling (measured 19px of document overflow at
   360x780); everything else merely got clipped. It wraps now. */
/* PATH08-REUSABLE-VISUAL-ACCEPTANCE-AND-UI-CLOSURE-01: the three filter groups on
   this row are one set — Поиск, Статус, Период — and the first two are 48px.
   Measured at 2560x1440 on the receptionist's workstation: this group was 36px,
   so it sat 12px shorter than the status select beside it and, centred by
   `.ro-board-tools`, pushed its «Период» caption 6px below the other two. The
   group is now the same 48px, its chips centred inside it; the chips keep their
   48px overlay targets and the row still wraps on a narrow board. */
.ro-periods { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; padding: 3px; min-height: 48px; max-width: 100%; background: var(--gt-surface-2); border-radius: 999px; }
.ro-period {
  padding: 5px 12px; border-radius: 999px; font-size: 0.82rem; font-weight: 600; white-space: nowrap;
  color: var(--gt-text-muted); text-decoration: none; transition: background .12s, color .12s;
}
.ro-period:hover, .ro-period:focus-visible { text-decoration: none; color: var(--gt-text); }
.ro-period.is-active { background: var(--gt-surface); color: var(--gt-accent); box-shadow: var(--gt-shadow-sm); }
/* R6M: "Свой период" is a chip inside the SAME .ro-periods group; its popover
   uses plain text date fields (no native date-input chrome the owner rejected).
   Owner correction (2026-07-22): the "Ещё" wrapper + "Все даты" are removed
   (.ro-period-more/.ro-period-more-body retired) — "Свой период" is now the
   only extra option, a direct sibling of the preset chips again, opening the
   calendar in one click; its summary is an icon-only glyph, not text. */
.ro-period-custom { position: relative; display: inline-flex; }
.ro-period-custom > summary { list-style: none; cursor: pointer; user-select: none; }
.ro-period-custom > summary::-webkit-details-marker { display: none; }
.ro-period-icon { display: inline-flex; align-items: center; justify-content: center; padding: 5px 10px; }
.ro-period-form {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 20;
  /* PATH08-RECEPTION-RESPONSIVE-BOARD-01: was a flat `width: 300px`, wider
     than the whole board on a phone. The ceiling is the VIEWPORT, deliberately
     not `max-width: 100%` — this box's containing block is the 36px calendar
     chip it hangs off, so a percentage ceiling would collapse it to 36px and
     spray the calendar grid out of its own popover. The narrow re-anchoring
     that keeps it inside the left edge too lives in the responsive block at
     the end of this stage. */
  /* PATH08-INSPECTION-PROGRESS-COHERENCE-01: 300px left the seven day columns
     about 40px wide, and a day cell is the one control in this product that
     CANNOT take an oversized hit area -- its neighbours are 4px away, so an
     overlay would be stolen by the cell next door (measured: 1 and 2 of the 4
     probes landed on a neighbour). The cells therefore grow for real, and the
     popover has to be wide enough to hold them: 380px gives 7 columns of about
     50px inside the 14px padding. The viewport ceiling is unchanged, so on a
     phone the popover still shrinks and the cells shrink with it -- there is no
     width at which 7x48px and a 360px screen can both be true. */
  display: block; width: min(380px, calc(100vw - 32px));
  padding: 14px; border: 1px solid var(--gt-border); border-radius: var(--gt-radius-md);
  background: var(--gt-surface); box-shadow: var(--gt-shadow-md);
}
/* R6M: custom clean calendar (range picker) — no native date-input chrome. */
.ro-cal { width: 100%; }
.ro-cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.ro-cal-navgrp { display: inline-flex; gap: 4px; }
.ro-cal-title { font-weight: 700; font-size: 0.9rem; color: var(--gt-text); font-variant-numeric: tabular-nums; }
.ro-cal-nav { width: 48px; height: 48px; border: 1px solid var(--gt-border); border-radius: 8px; background: var(--gt-surface); color: var(--gt-text-muted); font-size: 1.05rem; line-height: 1; cursor: pointer; }
.ro-cal-nav:hover { border-color: var(--gt-accent); color: var(--gt-accent); }
.ro-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.ro-cal-wd { text-align: center; font-size: 0.68rem; font-weight: 700; color: var(--gt-text-muted); padding: 4px 0; }
.ro-cal-day { min-height: 48px; border: 0; background: none; border-radius: 8px; cursor: pointer; font-size: 0.85rem; color: var(--gt-text); font-variant-numeric: tabular-nums; }
.ro-cal-day:hover { background: var(--gt-accent-soft); }
.ro-cal-day.is-in { background: var(--gt-accent-soft); border-radius: 0; }
.ro-cal-day.is-edge { background: var(--gt-accent); color: var(--gt-accent-solid-fg); }
.ro-cal-day.is-from { border-radius: 8px 0 0 8px; }
.ro-cal-day.is-to { border-radius: 0 8px 8px 0; }
.ro-cal-day.is-from.is-to { border-radius: 8px; }
/* PATH09-OWNER-RECEPTION-ACCEPTANCE-CONSOLIDATED-CORRECTION-01: a day standing alone — the first press, or the same day as start and end — is ONE rounded cell. It used
   to wear the left-only rounding of a range's first day and showed a cut right edge (the Owner, 2026-10-06). */
.ro-cal-day.is-edge.is-single { border-radius: 8px; }
/* The calendar chip names the range in force, because the calendar no longer stands open to say it. */
.ro-period-icon .ro-period-range { margin-left: 6px; font-size: 0.82rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* A box the board's live search refreshes in place; `display: contents` keeps it out of the layout, so the list, the
   period chips and the ✕ inside «Поиск» are laid out exactly as before. */
.ro-view-slot { display: contents; }
.ro-cal-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--gt-border); }
.ro-cal-range { font-size: 0.8rem; color: var(--gt-text-muted); font-variant-numeric: tabular-nums; }
.ro-cal-actions { display: flex; gap: 8px; flex: none; }
.rc-btn-sm { padding: 8px 14px; font-size: 0.82rem; }

/* ── Situation rows ──────────────────────────────────────────────────── */
/* R6P-2: compacted (owner visual acceptance — target ~9-10 cards per page with
   no scroll on the accepted desktop layout). Row gap/padding/gaps/font-sizes
   reduced; the former 3rd "timeline" line was folded into line 2 (see below),
   so each card is 2 lines instead of 3 — the main height driver removed. */
/* R6P-2: the list (not a fixed row count) is what fills the real screen —
   `.ro-list`'s own `flex: 1` lets IT grow to take whatever height `.ro-board`
   actually has available (so a full page of ~10 rows uses the real screen
   height with no dead gap below the pager). `min-height` on the row is the
   readable floor — below it the list scrolls internally rather than
   shrinking rows unreadably thin.
   R6Q-2b (owner-caught, 2 real bugs from letting ROWS themselves grow):
   (1) `flex: 1 1 0` (basis=0) made ALL rows equal height regardless of
   content — a short draft card (no progress bar/tags) stretched into a tall
   block of dead white space to match a content-heavy card on the same page.
   (2) even with `flex: 1 1 auto`, a SHORT LIST (e.g. one row under the
   "Аннулированные" filter) still has grow-factor 1 with nothing to compete
   against, so that one row absorbed ALL the container's leftover space and
   ballooned to fill the entire screen — same bad look, worse with fewer rows.
   Fix: rows do NOT grow at all (`flex: none` = natural content height, never
   stretched). A short filtered list simply leaves blank space below it
   (normal, expected — like any filtered table) instead of distorting cards;
   a full page of ~10 rows still comfortably fills the screen on its own
   because there is nothing left to stretch. */
/* R6Q-2d: padding on the scroll container matters here, not just cosmetics —
   `overflow-y: auto` forces the browser to also compute overflow-x as
   non-visible (auto), which was clipping each row's box-shadow flat at the
   list's own edge (the "straight edge" the owner kept seeing was the shadow
   being cut off, not a rendering bug in the shadow itself). Padding gives the
   shadow room to actually render before hitting that clip boundary. */
/* The one line a table owes the eye. It shares the row's own template AND the row's own content box:
   it is the first child of `.ro-list`, so the list's padding, the 1600px cap that centres it and the
   scrollbar a long list adds all apply to the heading and to the rows alike — a heading outside that
   box sat visibly off the columns it named at 2560. Its inline padding is the row's (26px / 30px)
   plus the row's 1px transparent border. Hidden below the workstation width, where the row stops
   being this grid. */
/* It stays in view while the list scrolls under it: `position: sticky` keeps it in the list's own
   content box, so the alignment above survives, and an OPAQUE page surface with a stacking level above
   the rows (`.ro-row` is positioned) stops row text showing through it. The list has padding above its
   first row, and a sticky box is held INSIDE that padding, so the heading takes the padding as its own
   (negative margin and offset, padding added back) — otherwise rows scroll through the strip above it. */
.ro-list-head {
  flex: none; position: sticky; top: calc(-1 * var(--gt-space-2)); z-index: 3; background: var(--gt-bg);
  margin-top: calc(-1 * var(--gt-space-2));
  display: grid; grid-template-columns: 1.1fr 1.45fr 1.55fr 1.2fr 96px 20px;
  column-gap: 24px; padding: calc(var(--gt-space-2) + 2px) 27px 6px 31px;
  font-size: 0.78rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--gt-text-soft);
}
.ro-list { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: var(--gt-space-3); overflow-y: auto; padding: var(--gt-space-2); }
/* R6Q-2c: owner-flagged the flat 1px border + single tight shadow as looking
   "unfinished" (a hard rectangular silhouette, no real depth). Replaced with a
   borderless card lifted by a two-layer soft shadow (a close, low-opacity
   contact shadow + a wider, softer ambient one) — a rounded card should read
   as elevated, not outlined. Scoped to .ro-row only; the shared --gt-shadow-*
   tokens are used in ~28 other places and are out of scope for this fix. */
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-01, accepted 2026-09-19
   (docs/kb/SOURCES/2026-09-19_owner_accepts_finished_reception_board.txt, «принимаю» to
   p01f_board_full_names.png): THE ROW IS A TABLE. Six columns —
   Автомобиль / Клиент / Состояние · механик / Итог / номер / стрелка — at
   1.1fr / 1.45fr / 1.55fr / 1.2fr / 96px / 20px with a 24px gap, the proportions measured on the
   physical 2560x1440 workstation so that a full ФИО holds one line («GT TEST Воскресенский
   Константин Александрович»), and ten rows of the tallest kind fit without the board scrolling.

   WHY A GRID AND NOT THE OLD FLEX BAND. The band shrank its children against each other, so every
   width needed a rule about who yields to whom, and the rail had to be capped at 40% to stop it
   eating the identity. Columns cannot starve each other: `fr` shares what is left AFTER the two
   fixed columns, identically on every row, which is what makes the list read DOWN — the thing a
   person scanning ten inspections actually does. */
.ro-row {
  position: relative; flex: none; min-height: 88px; overflow: hidden;
  display: grid; grid-template-columns: 1.1fr 1.45fr 1.55fr 1.2fr 96px 20px;
  column-gap: 24px; align-items: center; padding: 10px 26px 10px 30px;
  border: 1px solid transparent; border-radius: var(--gt-radius-lg);
  background: var(--gt-surface);
  box-shadow: 0 1px 2px rgba(22, 31, 45, .06), 0 10px 28px -6px rgba(22, 31, 45, .16);
  text-decoration: none; color: inherit;
  transition: box-shadow .12s;
}
/* R6M: no translateX on hover — the 2px shift caused a jerky reflow on load /
   hover. Hover now only changes shadow (no layout movement, no border color
   flip now that the row is borderless). */
.ro-row:hover { box-shadow: 0 2px 4px rgba(22, 31, 45, .08), 0 16px 36px -6px rgba(22, 31, 45, .22); }
.ro-row:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--gt-focus-ring); }
.ro-row.is-current { box-shadow: inset 0 0 0 1px var(--gt-accent), 0 1px 2px rgba(22, 31, 45, .06), 0 10px 28px -6px rgba(22, 31, 45, .16); }

/* The state stripe is NOT deleted with the band. Below the workstation width it is still how a row
   says its state at a glance, `.rc-ctx-card`/`.rc-detail-hero` draw it on two other surfaces, and the
   stacked phone row keeps it beside the chevron. The accepted workstation row simply does not carry
   it — the state has a named chip of its own there. */
.ro-accent { display: none; flex: none; width: 5px; align-self: stretch; background: var(--gt-border); }
.ro-s-draft .ro-accent { background: var(--gt-status-draft-accent); }
.ro-s-in_progress .ro-accent { background: var(--gt-warning); }
.ro-s-completed .ro-accent { background: var(--gt-success); }
.ro-s-cancelled .ro-accent { background: var(--gt-status-cancelled-accent); }
.ro-s-annulled .ro-accent { background: var(--gt-status-annulled-accent); }
.ro-s-unknown .ro-accent { background: var(--gt-warning); }  /* R6Q-1: slate-purple, distinct from cancelled grey */

/* Every column is a small stack: the fact that identifies it, then the facts that qualify it. One
   rule for all four, so a new column cannot invent its own spacing. */
.ro-cell { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.ro-sub { display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 8px; font-size: 0.8rem; color: var(--gt-text-soft); }
/* «Пробег НАД VIN» (accepted portion 1): the mileage is a fact about this visit, the identifier is a
   fact about the car, and one under the other is how the accepted picture reads them. Scoped to the
   car's cell — the state's own sub-line («механик · создан ДД.ММ») is one line on purpose. */
.ro-cell-car .ro-sub { flex-direction: column; gap: 1px; }
.ro-state-line { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
/* The result column is a row of tags, vertically centred against the two-line columns beside it. */
.ro-cell-result { flex-direction: row; flex-wrap: wrap; align-content: center; align-items: center; gap: 4px 6px; }
/* R6P-2: "Осмотр №N" — a client/mechanic-independent marker, visible on every
   card (and on the detail page hero). Muted so it never competes with the
   vehicle name for attention. */
.ro-num { font-size: 0.8rem; font-weight: 700; color: var(--gt-text-soft); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
/* THE IDENTIFIER IS NEVER SQUEEZED — the rule of
   PATH08-OB-REL-006-…-CORRECTION-01 (finding F1), now true by structure rather than by a shrink
   factor: the VIN has a line of its own under the car, so there is nothing beside it to take its
   width. A VIN is not prose; a part of it is not a recognisable part of it.
   The NAMES, which are prose, wrap instead of being ellipsised — measured on the accepted picture:
   one line up to «GT TEST Воскресенский Константин Александрович», two only for a 51-character
   client name or a 44-character car name. An ellipsis in a column this wide would hide the end of a
   surname while the space to print it was sitting right there on the next line. */
.ro-veh { min-width: 0; font-weight: 700; font-size: 1.05rem; color: var(--gt-text); overflow-wrap: anywhere; }
.ro-km { font-weight: 600; color: var(--gt-text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ro-vin { white-space: nowrap; font-variant-numeric: tabular-nums; }
/* R6M: status pill sits inline right after the title (was margin-left:auto,
   which floated it alone to the top-right while the chevron sat mid-right —
   two right-edge elements at different heights, which read as unbalanced). */
.ro-state-line .ro-chip { flex: none; }
/* PATH08-RECEPTION-UI-COHERENCE-01: `.ro-chip` carried NO colour or background
   rule of its own (the R6U note beside `.ro-paused-badge` below named that gap
   and left it), so the board rendered the state as bare text while the detail
   page and the results screen rendered the same state as a coloured pill. Same
   state, same walk, same chip language -- the token pairs are the ones
   `.rc-chip-*` already uses, not new values. */
.ro-chip {
  display: inline-flex; align-items: center; padding: 3px 11px;
  border-radius: 999px; font-size: 0.78rem; font-weight: 700; white-space: nowrap;
}
.ro-chip-draft { background: var(--gt-status-draft-chip-bg); color: var(--gt-status-draft-chip-fg); }
.ro-chip-in_progress { background: var(--gt-warning-bg); color: var(--gt-warning); }
.ro-chip-completed { background: var(--gt-success-bg); color: var(--gt-success); }
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-FIDELITY-01 (accepted 2026-09-19, portion 1): «Отменён» and «Аннулирован» are a
   grey outlined mark — a finished-without-result state, not an alarm. */
.ro-chip-cancelled, .ro-chip-annulled { background: transparent; color: var(--gt-text-muted); box-shadow: inset 0 0 0 1px var(--gt-field-border); }
/* A status this build does not recognise. It reads as "look at this", which is
   the truth, and it reuses the warning pair rather than minting a token family
   for a state that must never occur. */
.ro-chip-unknown { background: var(--gt-warning-bg); color: var(--gt-warning); }

/* R6U: paused is a read-only sub-badge, not a status of its own — same
   slate-purple accent language as the annulled chip (#8B7FC0), so it reads as
   "administrative note" rather than a new success/warning/danger state.
   Self-contained (does not reuse .ro-chip, which has no color/background rule
   of its own today — a pre-existing gap out of this stage's scope). */
.ro-paused-badge {
  flex: none; display: inline-flex; align-items: center; padding: 3px 11px;
  border-radius: 999px; font-size: 0.78rem; font-weight: 700; white-space: nowrap;
  background: var(--gt-status-admin-chip-bg); color: var(--gt-status-admin-chip-fg);
}

/* The client's number is shown exactly as it is stored — digits, no «+», brackets or dashes
   (docs/kb/SOURCES/2026-09-19_owner_phone_shown_as_stored_no_found_label.txt). Tabular figures so a
   column of numbers lines up. */
.ro-client { min-width: 0; font-weight: 600; font-size: 0.95rem; color: var(--gt-text); overflow-wrap: anywhere; }
.ro-phone { font-variant-numeric: tabular-nums; white-space: nowrap; }
.ro-mech { min-width: 0; color: var(--gt-text-muted); overflow-wrap: anywhere; }
/* «создан 17.09» only when the inspection is not from today — the filter this board opens on says
   «Сегодня», so the date earns its place exactly when it contradicts that. */
.ro-made { white-space: nowrap; }
.ro-made::before { content: "· "; }

/* THE RING, AND NO NUMBERS. «у „В работе“ — только кольцо выполнения, без чисел „18/163“». The pair
   is not lost, only taken off the visual layer: it is the ring's `title` and its accessible name, so
   a person who wants the exact count can still reach it and a screen reader still reads it. */
.ro-ring { flex: none; display: inline-flex; align-items: center; color: var(--gt-warning); }
.ro-ring.is-complete { color: var(--gt-success); }
/* The track has to be VISIBLE or the ring is not a ring, it is a stray arc: a quarter drawn against
   nothing reads as a decoration, the same quarter drawn against a full circle reads as «a quarter of
   the way». `--gt-border` is the sheet's own hairline colour and holds on both themes. */
.ro-ring-track { stroke: var(--gt-border); }
.ro-ring-fill { stroke: currentColor; }
/* R6M: "время выполнения" — the important param that was missing; lightly
   emphasised so it reads above the muted create/take/complete stamps. */
.ro-dur { color: var(--gt-text-muted); }
.ro-dur b { color: var(--gt-accent); }

/* The right-hand metrics rail and the board's own progress BAR are gone with the band: the facts
   they carried are in the result column and in the ring. `.rc-prog*` on the inspection page is a
   different control and keeps its rules below. */
/* PATH08-RECEPTION-RESPONSIVE-BOARD-01: `white-space: nowrap` — a tag is one
   atomic fact ("1 234 567 км"); now that `.ro-side` is allowed to narrow, a
   tag left free to break internally would split that fact across two lines
   instead of moving whole to the next line. */
.ro-tag { display: inline-flex; align-items: center; padding: 2px 9px; border-radius: 7px; font-size: 0.78rem; font-weight: 600; white-space: nowrap; background: var(--gt-surface-2); color: var(--gt-text); }
.ro-tag-ok { background: var(--gt-success-bg); color: var(--gt-success); }
/* The mechanic's «не применимо» decision on a board row. Same slate-purple
   «administrative note» tone as the annulled chip: it is a fact about the car,
   not a warning and not a success. */
.ro-tag-na { background: var(--gt-status-admin-chip-bg); color: var(--gt-status-admin-chip-fg); }
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-01: a finished inspection whose car has no VIN and no frame number.
   It is the one thing standing between the result and the client, so it carries the warning tone rather than
   the neutral one — and never the danger tone, which belongs to the remarks beside it. */
.ro-tag-vin { background: var(--gt-warning-bg); color: var(--gt-warning); }
/* «за N мин» — the measured working time, lightly emphasised above the neutral tags beside it. */
.ro-tag-dur { color: var(--gt-text-muted); }

/* "Requires decision" — the spine signal when defects exist (danger, prominent). */
.ro-decide {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  padding: 3px 11px; border-radius: 8px;
  background: var(--gt-danger-bg); color: var(--gt-danger);
  font-size: 0.82rem; font-weight: 700;
}
.ro-decide svg { width: 15px; height: 15px; flex: none; }
.ro-decide-sm { font-size: 0.78rem; padding: 2px 9px; }
.ro-decide-block { display: flex; justify-content: center; margin: 4px 0 14px; padding: 8px 12px; }

.ro-open { display: inline-flex; align-items: center; justify-content: center; color: var(--gt-text-muted); }
.ro-open svg { width: 18px; height: 18px; }
.ro-row:hover .ro-open { color: var(--gt-accent); }

/* `.ro-row-sm` was a compact variant of the old band; no template draws it. */

/* ── Completed (de-emphasized, collapsible) ──────────────────────────── */
.ro-done { margin-top: 24px; }
.ro-done-sum { display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: 1.02rem; font-weight: 700; color: var(--gt-text-muted); list-style: none; padding: 6px 0; }
.ro-done-sum::-webkit-details-marker { display: none; }
.ro-done-sum::before { content: "\25B8"; color: var(--gt-text-soft); display: inline-block; transition: transform .12s; }
.ro-done[open] .ro-done-sum::before { transform: rotate(90deg); }
.ro-list-done { margin-top: 10px; }
.ro-list-done .ro-row { background: var(--gt-surface-muted); }

/* ── Empty ───────────────────────────────────────────────────────────── */
.ro-empty { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 46px 26px; text-align: center; color: var(--gt-text-muted); border: 1px dashed var(--gt-border); border-radius: var(--gt-radius-lg); background: var(--gt-surface); }
.ro-empty p { margin: 0; }
.ro-empty-ic { width: 42px; height: 42px; color: var(--gt-border); }
/* PATH08-RECEPTION-UI-COHERENCE-01: an empty board names every filter in force
   -- two of the three are applied by default, without the receptionist having
   chosen them -- and carries the one control that drops all of them. */
.ro-empty-title { color: var(--gt-text); font-weight: 600; font-size: 1.02rem; }
.ro-empty-why { font-size: 0.9rem; }
.ro-empty-filters {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 8px;
  margin: 0; padding: 0; list-style: none; max-width: 100%;
}
.ro-empty-filter {
  display: inline-flex; align-items: baseline; gap: 6px; min-width: 0;
  padding: 4px 11px; border-radius: 999px;
  background: var(--gt-surface-2); border: 1px solid var(--gt-border);
}
.ro-empty-filter-name { font-size: 0.72rem; text-transform: uppercase; letter-spacing: .04em; color: var(--gt-text-muted); }
.ro-empty-filter-value { font-size: 0.86rem; font-weight: 600; color: var(--gt-text); overflow-wrap: anywhere; }
.ro-empty-reset { margin-top: 4px; }

/* Context card + detail hero reuse the .ro-s-{status} accent stripe. */
.rc-ctx-card .ro-accent, .rc-detail-hero .ro-accent { width: 6px; }
/* R6M: an inspection row spanning the full ~1360px canvas left the content
   clustered on the left with a large dead gap on the right (status chip alone
   top-right, chevron floating mid-right). Cap the list (and its header, so the
   filters stay aligned with the rows) to a comfortable reading width. */
/* R6M: use the big screen — the board rows were capped at 820px and left a lot
   of empty space on wide monitors. Give them room.
   Owner report (2026-07-22, 2K+ staff monitors, strategy correction): raising
   this cap further (tried min(98vw,3200px)) was rejected live — stretching
   short-content rows edge-to-edge across a 2K+ screen reads as a sparse,
   elongated "sausage", not a filled layout. Reverted to the 1600px reading
   cap and centered it instead (margin: 0 auto) — .ro-board's grid cell is
   wider than 1600px on 2K+ screens, and without centering these were
   left-aligned inside it, so the "unused space" the owner saw was actually
   the board sitting flush-left with a dead gap on the right, not the cap
   itself being too small. The 2K width now goes to a wider left icon rail
   (.gt-rail, see the 1920px+ media query near its definition) instead. */
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-FIDELITY-01: the board uses the whole 2560 screen (accepted 2026-09-19,
   portion 2); the cap left a strip of the screen empty beside it. */
.ro-board-head, .ro-list, .ro-done { width: 100%; max-width: none; margin-left: auto; margin-right: auto; }

/* ── Responsive (PATH08-RECEPTION-RESPONSIVE-BOARD-01, 2026-09-02) ──────
   From here down the board column is tight enough that the metrics rail's own
   max-content width — 459px measured on the densest real row — leaves the
   identity almost nothing: 88px of body at 1024 CSS px, where the vehicle
   name, the client and the mechanic all live. Capped at 40% of the row, the
   rail folds its tags onto a second line and the identity keeps the majority.

   1500 is a MEASURED boundary, not a round number. Above it the row already
   holds the whole first line of a typical card at its natural size, so the
   cap is not applied and the accepted desktop geometry is unchanged to the
   pixel (verified at 1600, 1920, 2560 and 3440: zero differing boxes against
   the pre-delivery stylesheet). Below it, line 1 misses by a handful of pixels
   and would otherwise wrap — which costs 25px of row height, six visible
   cards instead of seven at 1440x900. Capping the rail instead costs 4px,
   because the rail's tags fold into height the row's own 88px floor was
   already paying for. */
/* ── the row below the workstation width ──────────────────────────────────────────────────────
   THE ACCEPTED SIX-COLUMN TABLE IS A WORKSTATION LAYOUT. It was measured on 2560x1440, and its
   narrowest column (the result) needs room for a tag that cannot be broken. Below 1200px the four
   columns pair up into two ROWS of two — the car above the client, the state above the result —
   and the stripe and the chevron take their real positions again, spanning both rows exactly as
   they always did. Nothing here is a different set of facts: the same four cells, folded.

   1200px is where the board's shell stops being a fixed two-column box (see the workspace rules),
   so the board stops being able to hold four columns at the same moment it stops being a sidebar
   plus a list. One breakpoint for one reason, instead of a ladder of them. */
@media (max-width: 1199px) {
  .ro-list-head { display: none; }
  .ro-row {
    grid-template-columns: 5px minmax(0, 1fr) minmax(0, 1fr) auto 20px;
    grid-template-areas:
      "accent car    state  num open"
      "accent client result num open";
    column-gap: 16px; row-gap: 8px; align-items: start; padding: 12px 14px 12px 0;
  }
  .ro-accent { display: block; grid-area: accent; }
  .ro-cell-car { grid-area: car; }
  .ro-cell-client { grid-area: client; }
  .ro-cell-state { grid-area: state; }
  .ro-cell-result { grid-area: result; }
  .ro-num { grid-area: num; align-self: center; }
  .ro-open { grid-area: open; align-self: center; }
  /* The first cell of a folded row needs the left padding the stripe used to sit against. */
  .ro-cell-car, .ro-cell-client { padding-left: 10px; }
}

/* Below this width two columns no longer fit either: the result column's widest single tag and the
   state's chip plus ring cannot share a line with anything. The row becomes ONE column — the four
   cells and the inspection's number stacked — with the stripe and the chevron still spanning it,
   which is what a phone-width row has always looked like here. 719px is the measured ceiling: the
   board is `viewport - 176` once the shell has stacked, so 719 gives a 543px row. */
@media (max-width: 719px) {
  .ro-row {
    grid-template-columns: 5px minmax(0, 1fr) 20px;
    grid-template-areas:
      "accent car    open"
      "accent client open"
      "accent state  open"
      "accent result open"
      "accent num    open";
    row-gap: 6px;
  }
  .ro-num { align-self: start; text-align: left; }
  /* The calendar popover is anchored to the chip that opens it, and that chip can now sit anywhere
     in a wrapped row — with `right: 0` on a 300px box the popover's LEFT edge went negative and
     reintroduced page-level horizontal scrolling. Re-anchored to the chip GROUP, which always
     spans the board's own width. */
  .ro-period-custom { position: static; }
  .ro-periods { position: relative; }
  .ro-period-form { left: 0; right: auto; width: 100%; max-width: 320px; }
}
/* ═══ end Stage R2D ══════════════════════════════════════════════════════ */
/* ═══ Stage R3 — Inspection Report Workspace (detail) ════════════════════ */
/* Report header (vehicle-first) + Обзор/Результаты tabs (CSS radio, no JS) +
   issue-first result cards. Colors via .theme-light tokens; blue-teal accent;
   GT red never a primary action, only defect/danger. */

.rw-ident { min-width: 0; }
.rw-client { font-weight: 600; color: var(--gt-text); }
.rw-meta { color: var(--gt-text-muted); }
.rc-metric-ok .rc-metric-num { color: var(--gt-success); }

/* ── Tabs (radio-driven, no JS) ──────────────────────────────────────── */
/* R6M: the Обзор/Результаты radio-tab machinery was removed — the summary and
   the grouped faults are now on one scroll (no tab dive; §16.6 / Law 4). */
.rw-summary { margin-top: 2px; }
.rc-facts-strip { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px 20px; padding-top: 14px; margin-top: 16px; }
/* R6M: mechanic remarks block (free-text answers / non-fault notes). */
.rw-remarks { margin-top: 22px; }
.rw-remarks .rc-card-title { margin-bottom: 12px; }
.rw-remarks-list { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 8px; }
.rw-remark { padding: 12px 14px; border: 1px solid var(--gt-border); border-radius: var(--gt-radius-md); background: var(--gt-surface); }
.rw-remark-label { display: block; font-size: 0.82rem; font-weight: 700; color: var(--gt-text-muted); margin-bottom: 3px; }
.rw-remark-text { color: var(--gt-text); overflow-wrap: anywhere; }
.rw-results { margin-top: 22px; }
.rw-results-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px; }
.rw-results-n {
  display: inline-flex; align-items: center; padding: 2px 10px; border-radius: 999px;
  background: var(--gt-danger-bg); color: var(--gt-danger); font-size: 0.82rem; font-weight: 700;
}
.rw-clean {
  display: flex; align-items: center; gap: 10px; padding: 16px 18px;
  border: 1px solid var(--gt-success); border-radius: var(--gt-radius-md);
  background: var(--gt-success-bg); color: var(--gt-success); font-weight: 600;
}
.rw-clean svg { width: 22px; height: 22px; flex: none; }
/* PATH08-RECEPTION-UI-COHERENCE-01: `.rw-ready` and `.rw-ready-clean` are
   retired with the two summary banners they styled. Both restated the state,
   the count and the next step that the chip, the «Замечания» tile and the hero
   state line now each say once. Nothing renders them any more. */
/* R6M: NON-blocking VIN note — calm (not an alarm), available at any status, so
   the receptionist can add VIN whenever they like; the client PDF is the only
   thing gated on it. */
.rc-vin-note { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; margin-top: 12px; padding: 12px 14px; border: 1px solid var(--gt-border); border-radius: var(--gt-radius-md); background: var(--gt-surface-muted); }
/* PATH08-REUSABLE-VISUAL-ACCEPTANCE-AND-UI-CLOSURE-01: the VIN field and its
   «Сохранить» sit side by side as one entry. Measured at 2560x1440: the field is
   48px (`.rc-input`) and the small button beside it 44px, so the pair did not
   share a top or a bottom edge. The button takes the field's height here only. */
.rc-vin-note .rc-btn { min-height: 48px; }
.rc-vin-note-ic { width: 18px; height: 18px; flex: none; color: var(--gt-text-muted); }
.rc-vin-note-txt { flex: 1 1 240px; font-size: 0.86rem; color: var(--gt-text-muted); line-height: 1.4; }
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-FIDELITY-01: wide enough for its own hint («VIN или номер кузова»,
   accepted 2026-09-20 §4), and its refusal is a full-width red line under it. */
.rc-vin-input { flex: 0 1 300px; min-width: 240px; }
.rc-vin-note .rc-vin-err { flex-basis: 100%; margin: 2px 0 0; padding-left: 28px; }
/* The field and «Сохранить» stand right under the sentence (accepted 2026-09-19, portion 8), not at the far end of a
   2560 row, so the refusal line under them is under the field it is about. */
.rc-vin-note { flex-wrap: wrap; }
.rc-vin-note .rc-vin-note-txt { flex: 1 1 calc(100% - 40px); }
.rc-vin-note .rc-vin-input { margin-left: 28px; }
/* Disabled PDF action while VIN is missing (preview stays enabled). */
.rc-btn.is-disabled { opacity: .5; cursor: not-allowed; pointer-events: none; }
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-FIDELITY-01: «plainly grey until then» (accepted 2026-09-19, portion 8;
   colours from the 2026-09-20 contrast count: #5A646E light, #9AA7B3 dark), not a faded blue. */
.rc-btn.rc-btn-primary.is-disabled { opacity: 1; background: var(--gt-surface-2); color: #9AA7B3; border-color: var(--gt-field-border); box-shadow: none; }
.theme-light .rc-btn.rc-btn-primary.is-disabled { color: #5A646E; }

/* ── Result cards (issue-first) ──────────────────────────────────────── */
.rw-items { display: flex; flex-direction: column; gap: 10px; }
.rw-item {
  border: 1px solid var(--gt-border); border-left: 4px solid var(--gt-border);
  border-radius: var(--gt-radius-lg); background: var(--gt-surface);
  box-shadow: var(--gt-shadow-sm); padding: 14px 16px;
}
.rw-item-ok { border-left-color: var(--gt-success); }
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-01, accepted 2026-09-19 (portion 7): «неисправность — тёмная
   карточка с красной полосой слева». The red-tinted fill made five faults in a row a red wall in which no
   one line stood out; the stripe says «fault» and the text is read on the page's own surface. */
.rw-item-issue { border-left-color: var(--gt-danger); }
/* Deferred #138 resolver (2026-07-17): .rw-item-not_checked/-na/-skipped
   deleted here — confirmed dead (zero template/JS consumer anywhere,
   Owner-approved). A future "not checked"/"n/a"/"skipped" result-widget
   state needs its own new product decision, not a revival of these. */

.rw-item-head { display: flex; align-items: center; gap: 10px; }
.rw-item-n {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  min-width: 26px; height: 22px; padding: 0 7px; border-radius: 7px;
  background: var(--gt-surface-2); color: var(--gt-text-muted);
  font-size: 0.8rem; font-weight: 800; font-variant-numeric: tabular-nums;
}
.rw-item-label { flex: 1; min-width: 0; font-weight: 600; color: var(--gt-text); }
.rw-item-state { flex: none; padding: 3px 11px; border-radius: 999px; font-size: 0.78rem; font-weight: 700; white-space: nowrap; }
.rw-state-ok { background: var(--gt-success-bg); color: var(--gt-success); }
.rw-state-issue { background: var(--gt-danger-bg); color: var(--gt-danger); }
.rw-state-not_checked { background: var(--gt-surface-2); color: var(--gt-text-muted); }
/* Deferred #138 resolver (2026-07-17): .rw-state-na deleted here —
   confirmed dead (zero template/JS consumer anywhere, Owner-approved).
   A future "n/a" result-widget state needs its own new product
   decision, not a revival of this rule. */
.rw-state-skipped { background: var(--gt-surface-2); color: var(--gt-text-muted); }

.rw-defect { margin-top: 9px; color: var(--gt-danger); font-size: 0.92rem; }
.rw-defect strong { font-weight: 700; }
.rw-note { margin-top: 8px; color: var(--gt-text-muted); font-size: 0.9rem; white-space: pre-line; }
/* INSPECTION-PARTS-RUNTIME-DESIGN foundation: advisor-only, non-binding
   calculation-category hint — visually distinct from the defect line (not a
   diagnosis), advisor/owner detail page only. */
.rw-parts-hint { margin-top: 6px; color: var(--gt-text-muted); font-size: 0.86rem; }
.rw-parts-hint strong { color: var(--gt-text); font-weight: 600; }
.rw-copy-parts-btn {
  margin-left: auto; padding: 6px 14px; border: 1px solid var(--gt-border); border-radius: var(--gt-radius-md);
  background: var(--gt-surface); color: var(--gt-text); font-size: 0.84rem; font-weight: 600; cursor: pointer;
}
.rw-copy-parts-btn:hover { background: var(--gt-surface-muted); }
.rw-copy-parts-btn.is-copied { border-color: var(--gt-success); color: var(--gt-success); }
/* Off-screen but selectable — Clipboard-API-unavailable fallback selects this
   textarea's text so the advisor can Ctrl+C manually. Never visible. */
.rw-copy-parts-fallback {
  position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; overflow: hidden;
}
.rw-photos { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.rw-photo { width: 84px; height: 84px; object-fit: cover; border-radius: 10px; border: 1px solid var(--gt-border); display: block; }
/* ═══ end Stage R3 ══════════════════════════════════════════════════════ */

/* ═══ Stage R4 — report evidence-layer filters + facts-row overflow fix ══ */
/* CSS-radio-driven filter pills (no JS, matches the Обзор/Результаты tab
   pattern) over the already-rendered .rw-items list — purely a client-side
   show/hide, never removes an item from the DOM. "Все" (default) shows
   everything, so every result stays reachable regardless of which filter
   was last used. */
.rw-filters { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.rw-filter {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 13px; border-radius: 999px; border: 1px solid var(--gt-border);
  background: var(--gt-surface); color: var(--gt-text-muted);
  font-size: 0.86rem; font-weight: 700; cursor: pointer; user-select: none;
  transition: background .12s, border-color .12s, color .12s;
}
.rw-filter:hover { border-color: var(--gt-accent); color: var(--gt-text); }
.rw-filter-n {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 18px; padding: 0 6px; border-radius: 9px;
  background: var(--gt-surface-2); color: var(--gt-text-muted);
  font-size: 0.72rem; font-weight: 800;
}
/* Deferred #138 resolver (2026-07-17): the #rwf-*:checked ~ .rw-filters
   label[...] "active chip" rule pair (background/border/color for the
   label, and for its .rw-filter-n count badge) deleted here — confirmed
   dead (the #rwf-* radio inputs and .rw-filters markup they depend on
   are never rendered in any template, so :checked can never match;
   zero template/JS consumer anywhere, Owner-approved). A future filter-
   chip UI needs its own new product decision, not a revival of these
   rules. The item-hide rules immediately below are a distinct, separate
   concern (display:none toggling, not chip appearance) and are
   deliberately NOT part of this stage's named deletion scope. */
/* Filtering: hide non-matching items while a specific filter is active.
   No rule exists for #rwf-all — "Все" always shows every .rw-item. */
#rwf-issue:checked ~ .rw-items .rw-item:not(.rw-item-issue) { display: none; }
#rwf-photo:checked ~ .rw-items .rw-item:not(.rw-item-hasphoto) { display: none; }
#rwf-ok:checked ~ .rw-items .rw-item:not(.rw-item-ok) { display: none; }
#rwf-skipped:checked ~ .rw-items .rw-item:not(.rw-item-skipped) { display: none; }

/* R6K: staff Результаты grouped by system, each block COLLAPSED by default
   (<details>) with a fault-count label — no huge flat sheet, no filters. */
.rw-groups { display: flex; flex-direction: column; gap: 10px; }
.rw-group {
  border: 1px solid var(--gt-border); border-radius: var(--gt-radius-md);
  background: var(--gt-surface); overflow: hidden;
}
.rw-group-head {
  display: flex; align-items: center; gap: 10px; padding: 12px 16px;
  cursor: pointer; font-weight: 700; list-style: none;
  /* PATH08-INSPECTION-PROGRESS-COHERENCE-01: this heading declared no colour
     and inherited #6b7280 -- 3.41:1 on the DARK theme's card, the one AA
     failure the dark theme had. It is a section heading; primary text is what
     it should always have been, and the token is right in both themes. */
  color: var(--gt-text);
}
.rw-group-head::-webkit-details-marker { display: none; }
.rw-group-name { flex: 1 1 auto; }
.rw-group-name::before {
  content: "▸"; color: var(--gt-text-muted); margin-right: 8px;
  display: inline-block; transition: transform .12s;
}
.rw-group[open] .rw-group-name::before { transform: rotate(90deg); }
.rw-group-badge {
  font-size: 0.8rem; font-weight: 700; color: var(--gt-danger);
  background: var(--gt-danger-bg); border-radius: 20px; padding: 2px 10px;
}
/* R6P-2 (owner-caught, round 5): the collapsed group header must show BOTH
   the fault count AND the OK-photo count when a system has both — collapsing
   it into just one badge hid that confirmation evidence exists without
   opening the card. `.rw-group-badges` holds one or two pills side by side;
   `.rw-group-badge-ok` MUST be declared after `.rw-group-badge` (same
   specificity — source order decides the tie, and this rule needs to win
   when both classes are present on the "no faults" badge). */
.rw-group-badges { display: flex; align-items: center; gap: 6px; flex: none; }
.rw-group-badge-ok { background: var(--gt-success-bg); color: var(--gt-success); }
/* Deferred #138 resolver (2026-07-17): .rw-group-ok deleted here —
   confirmed dead (zero template/JS consumer anywhere, Owner-approved,
   distinct from the live .rw-group-badge-ok above). A future group-
   level "all ok" state needs its own new product decision, not a
   revival of this rule. */
.rw-group-total { font-size: 0.8rem; color: var(--gt-text-muted); }
.rw-group-body { display: flex; flex-direction: column; gap: 10px; padding: 4px 14px 14px; }

/* Facts-row overflow fix (deferred #40d): long unbreakable values (test/real
   phone numbers, long mechanic names) were visually colliding with the next
   grid column. min-width:0 lets the grid cell shrink below its content size;
   overflow-wrap lets the value itself wrap instead of overflowing. */
.rc-fact { min-width: 0; }
.rc-fact dd { overflow-wrap: anywhere; word-break: break-word; }
/* ═══ end Stage R4 ══════════════════════════════════════════════════════ */

/* ═══ PATH08-INSPECTION-PROGRESS-COHERENCE-01: a 48 CSS px target, and not one
   pixel of layout ═══════════════════════════════════════════════════════════
   Measured on the delivered pages at 2560x1440: the search clear was 22x22,
   the calendar arrows 28x28, a period chip 79x30, a calendar day 37x34, the
   cancel trigger 143x39 and the back link 221x22. Every one of them is a
   control a receptionist uses to do the job, and every one of them was well
   under a finger.

   HOW THE TARGET GROWS WITHOUT THE BOARD GROWING. The control keeps its exact
   painted size and gains an invisible, absolutely positioned `::after` centred
   on it, at least 48px in both directions. A pseudo-element is part of its
   originating element for hit testing, so the finger area is 48px while the
   box that participates in layout is unchanged -- the toolbar, the row height
   and the number of rows on a 2560x1440 screen are all exactly what they were.
   The overlays grow ONLY outward from the centre and never horizontally past a
   control that is already wide enough, so two adjacent chips do not fight over
   the gap between them.

   THE TWO THAT CANNOT DO THIS are the search field and the status select:
   replaced elements have no pseudo-element to hang a target on, so they grow
   for real, from 36px to 48px. That is the whole of this rule's layout cost --
   12px on one toolbar row, measured, and it takes no row off the board because
   the list already had 1229px for ten 98px rows. */
.ro-search-clear, .ro-period, .ro-pager-btn,
.rc-back, .rc-btn, .rw-group-head, .gt-rail-link,
.rc-inact > summary.rc-inact-trigger {
  position: relative;
}
/* The calendar's own two controls are deliberately NOT in this list: their
   neighbours are 4px away, so an oversized hit area would be taken by the cell
   next door. They are 48px for real instead. */
.ro-search-clear::after, .ro-period::after,
.ro-pager-btn::after, .rc-back::after, .rc-btn::after,
.rw-group-head::after, .gt-rail-link::after,
.rc-inact > summary.rc-inact-trigger::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 100%;
  min-width: 48px;
  height: 100%;
  min-height: 48px;
  /* Paints nothing and captures nothing that the control itself would not:
     it is the control's own hit area, made big enough for a finger. */
  border-radius: inherit;
}
/* The two replaced controls, which grow for real. */
.ro-search-input, .ro-status-select { height: 48px; }
.rc-input, .rc-select { min-height: 48px; }

/* ═══ Stage R6B: client-safe report — standalone document, no staff chrome ═══
   This is the client-facing report SOURCE, deterministic markup intended to
   be fed into a future server-side PDF renderer (R6C). Print rules here are
   NOT a claim that browser print is staff launch readiness (Constitution
   Sec.16.3) — they exist because R6C will render this exact template. */
.client-report-body { margin: 0; background: #fff; color: #1a1a1a; font-family: Inter, Arial, sans-serif; }
.client-report {
  max-width: 780px; margin: 0 auto; padding: 32px 28px 48px;
  box-sizing: border-box;
}
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-01, accepted 2026-09-19 (portion 9, «вариант Б»): a thin grey rule
   under the title instead of the thick red one. His words: «Б, названия и предпросмотр принимаю.» The band
   behind the logo keeps the brand; a red line across a document about someone's car read as an alarm. */
.client-report-head { border-bottom: 1px solid #d5dae0; padding-bottom: 14px; margin-bottom: 22px; }
/* R6I: the logo's wordmark is white (built for the dark app header), so it is
   placed on a dark brand band to render correctly on the white report. */
.client-report-brandbar {
  display: inline-flex; align-items: center; background: #16233a;
  padding: 9px 16px; border-radius: 10px; margin-bottom: 10px;
  -webkit-print-color-adjust: exact; print-color-adjust: exact;
}
.client-report-logo { display: block; height: 34px; width: auto; }
.client-report-title { margin: 6px 0 0; font-size: 1.5rem; font-weight: 700; }

.client-report-facts { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px 24px; margin-bottom: 24px; }
.client-report-fact { display: flex; flex-direction: column; min-width: 0; }
.client-report-fact-label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: .04em; color: #6b7280; }
.client-report-fact-value { font-size: 0.98rem; font-weight: 600; overflow-wrap: anywhere; }
/* A VIN is ONE identifier. The shared value class breaks anywhere it runs out
   of room, and a VIN split across two lines is a VIN a client copies wrong. */
.client-report-fact-vin { overflow-wrap: normal; word-break: keep-all; white-space: nowrap; }
/* ...AND ONE IDENTIFIER NEEDS ROOM TO BE ONE. Measured on the contour, in a real
   browser at 390x844: the VIN is 173px wide and its half-width column is 155px
   ((390 - 56 padding - 24 gap) / 2), so a client opening the report link on
   their phone read fourteen characters of a seventeen-character identifier and
   had no way to know the rest existed -- `nowrap` above kept it whole and the
   grid then cut it off.
   THE FIX IS ROOM, NOT WRAPPING. Removing `nowrap` would clear the clipping and
   reintroduce exactly the defect that rule exists to prevent, so the VIN cell
   takes the WHOLE row at the widths where half of one is not enough. 460px is
   above the measured threshold (a column reaches 173px at a 426px viewport) and
   below every other width this report is checked at, so 1024, 1440 and 2560 are
   untouched and so is the PDF. Every other fact keeps its column: they all
   carry `overflow-wrap: anywhere` and wrap safely. */
@media (max-width: 460px) {
  .client-report-fact-vin-cell { grid-column: 1 / -1; }
}

/* PATH08-RECEPTION-UI-COHERENCE-01. The summary is a <dl> now: three terms and
   their values, which is what these tiles have always been. The number carries
   its own declined noun ("5 пунктов"), so a tile reads as a phrase instead of a
   headline digit over a label that could not agree with it.
   CALM SEMANTIC EMPHASIS. The number is <strong>, so the emphasis lives in the
   markup and survives a black-and-white print and a screen reader; colour is
   the SECOND carrier now rather than the only one, and it is quieter — the
   alarm red #b3261e made an ordinary result look like a warning about the car.
   `.client-report-summary-nc` goes in the same pass: no markup in this template
   has ever carried that class. */
.client-report-summary { display: flex; gap: 10px 28px; margin: 0 0 28px; flex-wrap: wrap; }
.client-report-summary-item { display: flex; flex-direction: column; gap: 2px; min-width: 108px; }
.client-report-summary-n { margin: 0; font-size: 1.02rem; color: #1a1a1a; }
.client-report-summary-n strong { font-size: 1.34rem; font-weight: 700; line-height: 1.1; }
.client-report-summary-lbl { font-size: 0.72rem; text-transform: uppercase; letter-spacing: .04em; color: #6b7280; }
.client-report-summary-ok .client-report-summary-n strong { color: #15703f; }
.client-report-summary-issue .client-report-summary-n strong { color: #8a4b12; }
/* Zero findings is the best outcome on a client's document, and it stops being
   coloured like something that needs doing. */
.client-report-summary-zero .client-report-summary-n strong { color: #15703f; }
/* PATH08-INSPECTION-PROGRESS-COHERENCE-02. The COMPLETION tile is the primary
   fact on this document and the same fact the two staff screens show, so it
   leads the row and carries a little more weight than the three lanes that
   break it down. The «не применимо» lane wears the same quiet slate-purple the
   app uses everywhere for an administrative note -- it is a decision about the
   car, not a warning and not a success. */
.client-report-summary-primary { min-width: 150px; }
.client-report-summary-primary .client-report-summary-lbl { color: #374151; font-weight: 700; }
.client-report-summary-na .client-report-summary-n strong { color: #5a4f8f; }
/* The ASSESSED count, and it is a note rather than a tile on purpose: it
   answers a different question from «проверено», and a client must not be able
   to mistake the two for one number disagreeing with itself. */
.client-report-summary-note {
  margin: -18px 0 26px; font-size: 0.82rem; color: #6b7280;
}

.client-report-section-title { font-size: 1.05rem; font-weight: 700; margin: 18px 0 8px; }

/* R6H: findings grouped by system/section — compact, not one card per finding. */
.client-report-groups { display: flex; flex-direction: column; gap: 0; }
/* R6M: a tall group (e.g. Подвеска, 27 items) must be allowed to flow across a
   page break — forcing break-inside:avoid on the whole group pushed it wholesale
   to the next page and left a big empty gap (worse after the photos grew). Only
   an individual finding is kept whole. */
.client-report-group {
  border: 1px solid #e5e7eb; border-radius: 8px; padding: 10px 14px;
}
.client-report-group-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 6px; break-after: avoid; page-break-after: avoid; }
.client-report-group-counts { display: flex; align-items: center; gap: 6px; flex: none; }
.client-report-group-name { font-weight: 700; font-size: 0.98rem; }
/* The badge now says WHAT it counts («2 замечания»), so it is wider and must
   not wrap; and it is calm — a scarlet pill on every system that found anything
   turned a routine report into a page of alarms. */
.client-report-group-count { font-size: 0.78rem; font-weight: 600; color: #8a4b12; background: #fbf1e6; border-radius: 20px; padding: 1px 9px; white-space: nowrap; }
.client-report-group-list { margin: 0; padding: 0; list-style: none; }
.client-report-group-item { padding: 4px 0; font-size: 0.92rem; border-top: 1px solid #f3f4f6; break-inside: avoid; page-break-inside: avoid; }
.client-report-group-item:first-child { border-top: none; }
.client-report-item-row { display: flex; flex-wrap: wrap; gap: 4px 8px; }
.client-report-item-label { font-weight: 500; }
/* The defect text IS the finding, so it is the emphasised thing on its line —
   but by weight, at a calm tone, not by alarm colour. */
.client-report-item-defect { color: #8a4b12; font-weight: 600; }
/* R6M: a real fault the mechanic flagged but did not name a specific defect for
   — shown honestly (never an empty line), muted vs. a named defect. */
.client-report-item-attention { color: var(--gt-text-muted); font-style: italic; }
/* R6I: client-safe note + photos shown INLINE under the finding (no separate
   photo section — a photographed fault appears once, not duplicated). */
.client-report-item-note { color: #374151; font-size: 0.86rem; margin-top: 2px; white-space: pre-line; }
.client-report-item-photos { display: flex; gap: 10px; margin-top: 8px; flex-wrap: wrap; }
/* PATH08-CLIENT-REPORT-PAGINATION-CORRECTION-01 (the Owner, 2026-10-02, OWNER_DIRECT: the 13-page report's length and
   page breaks are not acceptable). A finding is atomic on a page, so the blank at the foot of a page is at most the next
   finding's height — and a finding with one photo stood the photo UNDER its title and every line of its text (title row,
   defect, note, then 232px of photo): a block of about 330px. A finding with exactly ONE photo and a short note (`-solo`, set
   by the template) now draws that photo in a fixed 236px column on the left, from the top of the finding, with the title row
   (label and badge) and the lines in the column beside it: the block is as tall as the photo. The badge keeps the column at the
   right edge of the page that the Owner accepted for every finding (variant A); the photo keeps its own bound (174-232px, its
   own shape, never cropped) and is not made smaller. Two or more photos, or a long note, keep the row of photos below. */
.client-report-item-text { min-width: 0; }
.client-report-item-solo { display: grid; grid-template-columns: 236px minmax(0, 1fr); grid-template-rows: auto auto 1fr; column-gap: 14px; align-items: start; }
.client-report-item-solo .client-report-item-main { display: contents; }
.client-report-item-solo .client-report-item-row { grid-column: 2; grid-row: 1; }
.client-report-item-solo .client-report-item-text { grid-column: 2; grid-row: 2; }
.client-report-item-solo .client-report-item-photos { grid-column: 1; grid-row: 1 / -1; margin-top: 2px; }
/* A finding with two or more photos, or with a long note (the template: over 300 characters; the limit is 2000), is the tall
   block (lines plus a row of photos, up to half a page or more). It may break INSIDE its note, but its photos stay with the
   last lines of that note, so a photo is never alone at the top of a page without words from its own finding; a short note
   (fewer than four lines) cannot split and the finding moves whole, as before. */
.client-report-group-item.client-report-item-flow { break-inside: auto; page-break-inside: auto; }
.client-report-item-flow .client-report-item-row,
.client-report-item-flow .client-report-item-defect,
.client-report-item-flow .client-report-item-answer { break-after: avoid; page-break-after: avoid; }
.client-report-item-flow .client-report-item-note { orphans: 2; widows: 2; }
.client-report-item-flow .client-report-item-photos { break-before: avoid; page-break-before: avoid; break-inside: avoid; page-break-inside: avoid; }
/* A heading is never the last thing on a page. */
.client-report-section-title { break-after: avoid; page-break-after: avoid; }
/* R6M: photos were 120×90 — too small for a client to see the defect. Enlarged
   to a legible size (still ~3 per row on A4). */
/* INSPECTION-STANDALONE-VISUAL-DELIVERY-CLOSURE-01-CORRECTION-01 — A PHOTO KEEPS ITS OWN SHAPE. The box used to be a
   fixed 232x174 filled by `object-fit: cover`, so every photo that was not 4:3 was cropped to fit it: a photo taken
   with the phone upright lost 22% at the top and 22% at the bottom, and the PDF embedded only that crop. The photo
   now scales inside a 232x232 bound with its own aspect ratio — portrait 174x232, landscape 232x174 as before. The
   174px floor keeps a box for the placeholder the report template draws for a failed photo, and `contain` letterboxes a
   photo narrower than that floor inside it instead of stretching or cropping it. */
.client-report-photo { width: auto; height: auto; max-width: 232px; max-height: 232px; min-width: 174px; min-height: 174px; object-fit: contain; border-radius: 6px; border: 1px solid #e5e7eb; }
.client-report-no-findings { color: #16794c; font-weight: 500; }
/* R6P-2: a system group whose only content is OK-item evidence photos (no
   fault) — same green "ok" tone as .client-report-no-findings, honest that
   nothing here needs attention. */
/* PATH08-RECEPTION-UI-COHERENCE-01: this class is retired with the badge it
   styled. Every confirmation says «без замечаний» on its own line inside the
   same card, so the badge repeated that exact phrase a few pixels above the
   lines that already carried it. */
/* PATH08-RECEPTION-UI-COHERENCE-01: uppercase, 700, and the strongest green on
   the page — the confirmation that nothing is wrong was shouting louder than
   the findings it sat beside. Quiet now: it is a verdict on a line, not a
   heading. */
.client-report-item-ok-lbl { font-size: 0.8rem; font-weight: 600; color: #15703f; }
.client-report-group-item-ok .client-report-item-label { font-weight: 500; }
/* R6M: mechanic remarks on the client report (free-text answers / non-fault notes). */
/* PATH08-CLIENT-REPORT-PDF-RESIDUALS-01 — the mechanic's free-text ANSWER, on
   the line of the question it answers. It replaced the «Замечания механика»
   list at the foot of the report, which printed the same answer a second time
   under a question that had ALSO been given an ordinary «без замечаний» line.
   Styled as content, not as a verdict: the ok/na labels are small muted words,
   this is the mechanic's sentence and reads as one. */
.client-report-item-answer { color: #1f2937; font-size: 0.92rem; white-space: pre-line; }

.client-report-disclaimer {
  margin-top: 32px; padding-top: 14px; border-top: 1px solid #e5e7eb;
  font-size: 0.82rem; color: #6b7280;
  /* PATH09-V4-CLIENT-PDF-PAGINATION-CORRECTION-01: the closing line is never alone on a printed page. When it does not
     fit under the last rows, those rows move to the next page with it. Measured: the GT TEST v4 report (4 findings
     needing attention, 61 in order, 7 photos) printed a third page holding this one line and the page footer. The
     template places it as the last child of `.client-report-findings` because Chrome honours this rule there. */
  break-before: avoid; page-break-before: avoid; break-inside: avoid; page-break-inside: avoid;
}

/* Print/PDF-friendly rules — consumed by the R6C server renderer (and dev/owner
   browser preview). Browser print itself is NOT staff launch readiness. */
@page { size: A4; margin: 16mm 14mm; }
/* PATH08-RECEPTION-UI-COHERENCE-01 -- EVERY PRINTED PAGE SAYS WHAT IT IS.
   A client holding page 3 of a printed report had nothing on it naming the car,
   and no way to tell whether the report ended there: the header block prints on
   page 1 and Chromium repeats nothing by itself.

   A `@page` margin box is the only mechanism here that repeats per page. It is
   a NAMED page, claimed by `.client-report-body` alone, so the rules below
   reach the client report and no other screen that anyone ever prints.

   `content` in a margin box accepts strings and counters and nothing else --
   which is why the identity arrives as the `--gt-report-identity` custom
   property, written by the template through `css_string` (see
   `app.inspection_status_display`), and why the page number is `counter(page)`
   / `counter(pages)` rather than markup. Both were measured in the project's
   own Chromium 131 before being written here; the fallback `""` keeps the
   footer empty rather than printing the word `var` if the property is ever
   missing. The bottom margin is 18mm (not the default 16mm) so the footer band
   never crowds the last line of content. */
.client-report-body { page: gt-client-report; }
@page gt-client-report {
  size: A4;
  margin: 16mm 14mm 18mm;
  /* The margin box inherits nothing from `body`, so the document's own stack is
     restated here — without it the footer printed in the browser's serif
     default beside a sans-serif report. */
  @bottom-left {
    content: var(--gt-report-identity, "");
    font-family: Inter, Arial, sans-serif;
    font-size: 8pt;
    color: #6b7280;
  }
  @bottom-right {
    content: "Стр. " counter(page) " из " counter(pages);
    /* PATH08-REUSABLE-VISUAL-ACCEPTANCE-AND-UI-CLOSURE-01: measured in the saved document of a car
       with a long name, every page read «Стр. 1 из» with its «7» on a second line — the long
       identity beside it took the width, and this box wrapped at its last space. */
    white-space: nowrap;
    font-family: Inter, Arial, sans-serif;
    font-size: 8pt;
    color: #6b7280;
  }
}
@media print {
  .client-report-body { background: #fff; }
  .client-report { max-width: none; padding: 0; }
  .client-report-group-item { break-inside: avoid; }
  /* A summary tile split across a page break shows a number with no label. */
  .client-report-summary-item { break-inside: avoid; page-break-inside: avoid; }
  /* PATH09-V4-CLIENT-PDF-PAGINATION-CORRECTION-01: on paper the closing line keeps its rule and its words with less air
     above them (32px on screen). The 18px saved is what let the v4 report's last line fit on page 2 instead of taking
     the last row of photos to a page 3 with it. */
  .client-report-disclaimer { margin-top: 14px; }
}
/* ═══ end Stage R6B ═════════════════════════════════════════════════════ */

/* ═══ Stage R6I: client-report preview as a modal dialog OVER the page ═══ */
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-01, accepted 2026-09-19 (portion 9): the preview shows the PDF's
   own pages «на всю высоту экрана (на 2560 — две рядом)», so the dialog is as large as the screen allows
   instead of a 940px reading column — the pages inside decide their own width. */
.rc-preview-modal {
  width: min(1900px, 96vw); max-height: 96vh; padding: 0; border: none;
  border-radius: var(--gt-radius-lg); background: var(--gt-surface);
  box-shadow: 0 24px 60px rgba(15, 23, 42, .35); overflow: hidden;
}
.rc-preview-modal::backdrop { background: rgba(15, 23, 42, .55); }
.rc-preview-modal[open] { display: flex; flex-direction: column; }
.rc-preview-modal-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 18px; border-bottom: 1px solid var(--gt-border); flex: 0 0 auto;
}
.rc-preview-modal-title { font-weight: 700; font-size: 1.02rem; }
.rc-preview-close {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 9px; border: 1px solid var(--gt-border);
  background: var(--gt-surface); color: var(--gt-text-muted); font-size: 1rem;
  cursor: pointer; transition: background .12s, color .12s;
}
.rc-preview-close:hover { background: var(--gt-surface-2); color: var(--gt-text); }
.rc-preview-frame { display: block; width: 100%; flex: 1 1 auto; height: 88vh; border: 0; background: #fff; }
/* ═══ end Stage R6I ═════════════════════════════════════════════════════ */

/* R6M: fault-photo lightbox (opens over the page, not a new tab). */
.rw-photo-link { display: inline-block; padding: 0; border: 1px solid var(--gt-border); border-radius: 8px; background: none; cursor: pointer; overflow: hidden; line-height: 0; transition: border-color .12s, box-shadow .12s; }
.rw-photo-link:hover { border-color: var(--gt-accent); box-shadow: var(--gt-shadow-sm); }
.rw-lightbox { padding: 0; border: 0; border-radius: var(--gt-radius-md); background: transparent; max-width: 92vw; max-height: 92vh; overflow: visible; }
.rw-lightbox::backdrop { background: rgba(15, 23, 42, .78); }
.rw-lightbox[open] { display: block; animation: rw-lb-in .18s ease both; }
.rw-lightbox[open]::backdrop { animation: rw-bd-in .18s ease both; }
.rw-lightbox.is-closing { animation: rw-lb-out .16s ease both; }
.rw-lightbox.is-closing::backdrop { animation: rw-bd-out .16s ease both; }
@keyframes rw-lb-in { from { opacity: 0; transform: scale(.95); } to { opacity: 1; transform: scale(1); } }
@keyframes rw-lb-out { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(.97); } }
@keyframes rw-bd-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes rw-bd-out { from { opacity: 1; } to { opacity: 0; } }
.rw-lightbox-img { display: block; max-width: 92vw; max-height: 92vh; border-radius: var(--gt-radius-md); box-shadow: var(--gt-shadow-lg); opacity: 0; transition: opacity .18s ease; }
.rw-lightbox-img.is-loaded { opacity: 1; }
.rw-lightbox-close {
  position: absolute; top: -14px; right: -14px; width: 36px; height: 36px; z-index: 2;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 50%; background: var(--gt-surface); color: var(--gt-text);
  box-shadow: var(--gt-shadow-md); font-size: 1.1rem; cursor: pointer;
}
.rw-lightbox-close:hover { background: var(--gt-surface-2); }

/* R6P-2: prev/next carousel controls + "Фото N из M" position label. Simple
   plain-CSS/JS controls (no library) over the existing single-photo dialog. */
.rw-lightbox-nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 50%; background: var(--gt-surface); color: var(--gt-text);
  box-shadow: var(--gt-shadow-md); font-size: 1.6rem; line-height: 1; cursor: pointer;
}
.rw-lightbox-nav:hover { background: var(--gt-surface-2); }
.rw-lightbox-prev { left: -22px; }
.rw-lightbox-next { right: -22px; }
.rw-lightbox-pos {
  position: absolute; left: 50%; bottom: -34px; transform: translateX(-50%);
  padding: 5px 14px; border-radius: 999px; background: rgba(15, 23, 42, .78); color: var(--gt-lightbox-text);
  font-size: 0.82rem; font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums;
}

/* ============================================================
   DS-1 Gate 1: Inspection Launch Surface — visual composition
   (2026-07-17). Matches the accepted system reference's shell,
   typography, spacing, forms, states, and workspace patterns
   (docs/design-system/system-reference/gt-crm-system-reference.html,
   ADR 0020 §5) across the Inspection launch surface. Every rule in
   this section reuses EXISTING semantic tokens only — no new
   reference token was needed for this package. Where an existing
   token's Porcelain value differs slightly from a legacy ad-hoc hex
   it replaces (several of the lifecycle-check pages below had never
   been tokenized before — pure light-only raw hex, no Studio+Command
   support at all), that is an intentional consolidation onto the
   shared system palette: this package's mandate is system-wide
   visual consistency matching the reference, not byte-identical
   legacy preservation (distinct from earlier, narrower DS-1
   packages — see native_inspection_launch_contract.md Gate 1 for
   the scope note). Mechanic (.theme-dark/.mech-app) and the
   client-report print iframe (.rc-preview-frame/.rc-preview-modal*)
   are untouched by this section, per their own documented scope. */

/* ---- Typography (D4: base size raised toward the 14-15px range) ------ */
body { font-size: 15px; }
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-FIDELITY-01: desk pages (they carry the rail) read at 16px (portion 2). */
body:has(> .gt-rail) { font-size: 16px; }

/* ---- Page heading: optional eyebrow/subtitle pieces for .wo-list-header
   (the header rule itself was upgraded in place, above) ----------------- */
.gt-eyebrow {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--gt-text-soft);
  margin-bottom: 4px;
}
.gt-page-subtitle { margin: 4px 0 0; color: var(--gt-text-muted); font-size: 13.5px; }

/* ---- Shared panel/card — consolidates the lifecycle-check pages' former
   private rde-card/rpc-card/rac-card/rop-card/tcc-card duplicates (all
   were byte-identical: 1px border, 12px radius, ~14/16px padding, white
   background) onto ONE token-driven, theme-aware class. ------------------ */
.gt-panel {
  border: 1px solid var(--gt-border);
  border-radius: var(--gt-radius-lg);
  padding: 14px 16px;
  margin: 10px 0;
  background: var(--gt-surface);
}
.gt-meta, .rde-meta { color: var(--gt-text-muted); font-size: 13px; margin-top: 2px; }

/* ---- Notice: fourth state. .notice/.notice.good/.notice.neutral/
   .notice.danger already existed (DS-1B); .warn is new here, for the
   lifecycle-check pages' amber "this will delete X" confirmations —
   reuses the already-existing warning tokens, zero new color. --------- */
.notice.warn {
  background: var(--gt-warning-bg);
  border-color: var(--gt-state-warning-border);
  color: var(--gt-state-warning-fg);
}

/* ---- Lifecycle-check pages: page-specific structural pieces that have
   no generic equivalent (rde-* = draft editor, rop-* = structure preview,
   rac-*/rpc-* error lists shared by publish/activation/rollback checks).
   Moved here from each template's own private <style> block (deleted) —
   every raw hex below is now a token reference; both themes now render
   correctly where before only draft_edit.html had any dark-theme support
   at all. ---------------------------------------------------------------- */
.rpc-errors, .rac-errors { margin: 8px 0 0; padding-left: 20px; }

/* Live-proven fix (2026-07-19, properties-pane readability correction):
   the previous flex-wrap row let each flag's checkbox+label pair size to
   its OWN intrinsic (unwrapped) content width; once the properties pane
   narrowed (4-pane parity added a 4th, fixed-width sibling), no flag's
   full label fit on one row, so EVERY flag became the sole item on its
   own row anyway — but align-items:center then centered each 2-3-line
   wrapped label against its single-line checkbox, producing a staggered,
   inconsistently-indented "checklist" that measured as genuinely unreadable
   at real properties-pane widths. A single-column list with each label
   top-aligned against its checkbox reads correctly at ANY pane width,
   wrapping cleanly to 2 lines when needed instead of zigzagging. */
.rde-flags { display: flex; flex-direction: column; gap: 10px; margin: 12px 0 0; }
/* display:block (not flex) is deliberate: a flex row's anonymous text
   item fights the SAME "implicit min-size" class of bug already fixed
   elsewhere in this file (flex/grid items default to their UNWRAPPED
   content width unless min-width:0 is set on the item itself — and a
   bare text node, unlike an element, can never be targeted by a
   min-width:0 selector). Plain inline flow has no such failure mode: the
   checkbox is a normal inline-replaced element and the label text wraps
   naturally at the box edge, full-width, on every subsequent line. */
.rde-flag { display: block; font-size: 14px; line-height: 1.35; }
/* The page-wide `input, select, textarea { width: 100% }` rule (Forms,
   above) stretches a plain checkbox to the label's full width once the
   label is a normal block (it was invisibly absorbed/shrunk by the flex
   algorithm before) — pin it back to checkbox size explicitly. */
.rde-flag input[type="checkbox"] { width: 16px; height: 16px; margin-right: 8px; vertical-align: -3px; }
.rde-nav-bar {
  position: sticky; top: 0; z-index: 5;
  background: var(--gt-surface); border: 1px solid var(--gt-border); border-radius: 10px;
  padding: 10px 14px; margin: 20px 0 10px;
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
}
.rde-section-nav { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 14px; }
.rde-section { border: 1px solid var(--gt-border); border-radius: 12px; padding: 0 14px 14px; margin: 14px 0; background: var(--gt-surface-muted); }
.rde-section-summary { cursor: pointer; font-size: 1.25em; font-weight: 600; margin: 0; padding: 14px 0; list-style: none; }
.rde-section-summary::-webkit-details-marker { display: none; }
.rde-section-summary::before { content: "▸ "; }
details[open] > .rde-section-summary::before { content: "▾ "; }
.rde-target-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.4); z-index: 50; display: flex; align-items: flex-start; justify-content: center; padding: 40px 16px; }
.rde-target-overlay-inner { background: var(--gt-surface); border-radius: 12px; padding: 16px; width: 100%; max-width: 560px; max-height: 80vh; display: flex; flex-direction: column; }
#rde-target-list { overflow-y: auto; flex: 1; border: 1px solid var(--gt-border); border-radius: 8px; padding: 6px; }
.rde-target-group-label { font-weight: 600; padding: 6px 4px 2px; color: var(--gt-text-muted); }
.rde-target-option { padding: 6px 8px; border-radius: 6px; cursor: pointer; font-size: 14px; }
.rde-target-option:hover { background: var(--gt-accent-soft); }
.rde-target-picker { display: inline-flex; align-items: center; gap: 6px; }
.rde-target-display { color: var(--gt-text-muted); font-size: 13px; font-style: italic; }
.rde-skip-rule-form {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
  align-items: end;
  margin-top: 12px;
  padding: 12px;
  border: 1px solid var(--gt-border);
  border-radius: 10px;
  background: var(--gt-surface-muted);
}
.rde-skip-field { display: grid; gap: 5px; min-width: 0; }
.rde-skip-field > span,
.rde-skip-condition { color: var(--gt-text-muted); font-size: 13px; }
.rde-skip-field select { width: 100%; min-width: 0; }
.rde-skip-rule-form .rde-target-picker { align-self: stretch; min-width: 0; flex-wrap: wrap; }
.rde-skip-rule-form .rde-target-display {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 180px;
}
.rde-skip-submit:disabled { opacity: .45; cursor: not-allowed; }
.rde-skip-status { grid-column: 1 / -1; color: var(--gt-text-muted); font-size: 13px; }
.rde-skip-status.is-ready { color: var(--gt-success); }
.rde-hint-heading { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.rde-technical-code { font-size: 12px; color: var(--gt-text-muted); }
.rde-technical-code summary { cursor: pointer; }
.rde-technical-code code { display: block; margin-top: 4px; }
.rde-hint-search { width: 100%; max-width: 480px; margin: 6px 0; }

/* ---- Editor pane layout (DS-1 Gate 1 "editor workspace" mapping): the
   section nav becomes a sticky structure rail on wide viewports; the
   question cards remain in normal document flow to the right (the
   merged ledger+properties pane — separating those into two independent
   selection-driven panes would require a JS data-model rewrite, out of
   this bounded package's "presentation over the existing DOM" scope; see
   the launch contract's Gate 1 gap note). Bounded client-only JS (below,
   in the template) marks the currently-active section link — pure
   presentation, no new form/route/request. ------------------------------ */
.rde-editor-layout { display: flex; align-items: flex-start; gap: 20px; }
.rde-editor-rail {
  position: sticky; top: 66px; flex: 0 0 220px; align-self: flex-start;
  display: flex; flex-direction: column; gap: 4px;
  max-height: calc(100vh - 90px); overflow-y: auto;
  padding: 10px; border: 1px solid var(--gt-border); border-radius: 12px; background: var(--gt-surface);
}
.rde-editor-main { flex: 1 1 auto; min-width: 0; }
.rde-nav-link {
  display: block; padding: 8px 10px; border-radius: 8px; font-size: 13px; font-weight: 600;
  background: transparent; border: 1px solid transparent; color: var(--gt-text);
}
.rde-nav-link:hover { background: var(--gt-surface-2); }
.rde-nav-link.is-current { background: var(--gt-accent-soft); border-color: var(--gt-accent); }
@media (max-width: 960px) {
  .rde-editor-layout { flex-direction: column; }
  .rde-editor-rail { position: static; flex-direction: row; flex-wrap: wrap; max-height: none; width: 100%; }
  .rde-editor-preview { flex: 0 0 auto; width: 100%; max-height: none; min-width: 0; }
}

/* ---- Structure-preview (rop-*) — read-only ledger view ---------------- */
.rop-summary { display: flex; flex-wrap: wrap; gap: 16px; margin: 14px 0 18px; }
.rop-stat { background: var(--gt-surface-muted); border: 1px solid var(--gt-border); border-radius: 10px; padding: 10px 14px; min-width: 120px; }
.rop-stat b { display: block; font-size: 20px; }
.rop-text { font-weight: 600; }
.rop-badges { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 0; }
.rop-badge { font-size: 12px; padding: 3px 8px; border-radius: 999px; border: 1px solid var(--gt-border); background: var(--gt-badge-neutral-bg); color: var(--gt-splus-badge-neutral-fg); }
.rop-badge-on { background: var(--gt-result-all-clear-bg); border-color: var(--gt-result-item-ok-border); color: var(--gt-result-all-clear-fg); }
.rop-badge-off { background: var(--gt-surface-muted); border-color: var(--gt-border); color: var(--gt-text-muted); }
.rop-badge-gap { background: var(--gt-danger-bg); border-color: var(--gt-danger); color: var(--gt-state-danger-fg); }

/* ---- Template ledger (admin_inspection_templates.html) — lifecycle
   status chips, reusing the ALREADY-existing status-chip token families
   (draft/admin-candidate/all-clear) instead of the plain text cell the
   ledger rendered before. ------------------------------------------------ */
.gt-ledger-row:hover td { background: var(--gt-surface-2); }
.gt-lifecycle-chip { display: inline-flex; align-items: center; padding: 3px 10px; border-radius: 999px; font-size: 12px; font-weight: 700; white-space: nowrap; }
.gt-lifecycle-chip-draft { background: var(--gt-status-draft-chip-bg); color: var(--gt-status-draft-chip-fg); }
.gt-lifecycle-chip-candidate { background: var(--gt-status-admin-chip-bg); color: var(--gt-status-admin-chip-fg); }
.gt-lifecycle-chip-active { background: var(--gt-result-all-clear-bg); color: var(--gt-result-all-clear-fg); }
.gt-lifecycle-chip-archived { background: var(--gt-status-draft-chip-bg); color: var(--gt-status-draft-chip-fg); }

/* ============================================================
   DS-1 Gate 1 delta (2026-07-18): reception selectable ledger +
   details pane; editor sections/ledger/properties with single-question
   visibility. Matches the accepted reference's .gts-case-list +
   .gts-inspector (reception) and .gts-editor-layout (editor). Every rule
   below reuses existing tokens only — no new reference token needed.
   ============================================================ */

/* ---- Owner-approved Gate 1 reception ledger (2026-07-18): the closable
   drawer (.ro-drawer/.ro-drawer-head/.ro-drawer-close/.ro-details-*) is
   removed entirely, not just unreferenced — every one of these selectors
   was drawer-exclusive (unlike e.g. the old .header, which mechanic pages
   also consumed), so there is no "leave it dead" case here: deleting is
   the correct, complete removal. .ro-prog/.ro-prog-fill (used by the row
   itself, NOT drawer-exclusive) are untouched, further down this file. -- */

/* ---- Editor: 3-pane (structure rail already existed; ledger + properties
   are new) — matches .gts-editor-layout (structure|ledger|properties). --- */
.rde-editor-ledger, .rde-editor-properties {
  flex: 0 0 240px; min-width: 0;
  max-height: calc(100vh - 90px); overflow-y: auto;
  border: 1px solid var(--gt-border); border-radius: 12px; background: var(--gt-surface);
}
.rde-editor-properties { flex: 1 1 auto; }
/* Selected-section-only ledger, by default (browse mode); the "Развернуть
   все"/search escape hatch (JS removes .rde-browse-mode) reveals every
   section's ledger at once for a full audit view. */
.rde-ledger-pane { display: none; }
.rde-browse-mode .rde-ledger-pane.is-current { display: block; }
.rde-editor-layout:not(.rde-browse-mode) .rde-ledger-pane { display: block; }
.rde-ledger-pane-head { display: flex; align-items: center; justify-content: space-between; padding: 10px 14px; border-bottom: 1px solid var(--gt-border); font-weight: 600; }
.rde-ledger-pane-head small { color: var(--gt-text-muted); font-weight: 400; margin-left: 6px; }
.rde-tree-row {
  display: grid; grid-template-columns: 24px minmax(0, 1fr); align-items: center; gap: 8px;
  width: 100%; min-height: 44px; padding: 8px 14px; border: 0; border-bottom: 1px solid var(--gt-border);
  background: transparent; color: var(--gt-text); text-align: left; cursor: pointer; font-size: 13.5px;
}
.rde-tree-row b { color: var(--gt-text-muted); font-weight: 400; }
.rde-tree-row:hover { background: var(--gt-surface-2); }
.rde-tree-row.is-current { background: var(--gt-accent-soft); box-shadow: inset 3px 0 var(--gt-accent); }
/* Hide-inactive-content + show-exactly-one-question: the browse-mode class
   is present by default (removed by JS while a search query is active or
   "Развернуть все" was clicked) — a question card is visible ONLY if it
   carries .is-current while in browse mode. */
.rde-browse-mode .rde-question-card:not(.is-current) { display: none; }
.rde-question-card { scroll-margin-top: 80px; }

/* ---- 4-pane parity (2026-07-19): standalone preview pane, 4th sibling of
   rail/ledger/properties. Always shows exactly the CURRENT question's
   preview card regardless of browse mode — the preview mirrors "properties"
   selection, not "ledger" section visibility, so it is intentionally NOT
   wired to .rde-browse-mode. */
.rde-editor-preview {
  flex: 0 0 380px; min-width: 340px;
  max-height: calc(100vh - 90px); overflow-y: auto;
  border: 1px solid var(--gt-border); border-radius: 12px; background: var(--gt-surface-muted);
  padding: 16px;
}
.rde-preview-card { display: none; }
.rde-preview-card.is-current { display: block; }

/* ============================================================
   DS-1 Gate 1 final-fit (2026-07-18): contain the ledger pane's section
   toolbar so it never overflows/squeezes the narrow (240-280px) pane —
   the old single flex-wrap row let the rename <form>'s own min-width:220px
   exceed the pane's usable inner width, shrinking the input far below a
   usable size. Stacked layout: rename form gets its own full-width row
   (input >= 140px guaranteed even at the pane's narrowest, 240px, width);
   the 4 action buttons wrap onto their own row(s) below, never overflowing.
   ============================================================ */
.rde-section-toolbar { display: flex; flex-direction: column; gap: 10px; }
.rde-rename-form { display: flex; flex-direction: column; gap: 8px; }
.rde-rename-input { width: 100%; min-width: 140px; box-sizing: border-box; }
.rde-rename-save { width: 100%; text-align: center; white-space: normal; box-sizing: border-box; }
.rde-section-toolbar-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.rde-section-toolbar-actions form { flex: 0 0 auto; }
/* Extra breathing room at wide desktop viewports (the browser-acceptance
   review's own tested width) — not required for the >=140px minimum
   (already guaranteed by width:100% above at any pane width >=200px), but
   gives the rename input a more comfortable, less cramped feel when the
   viewport has room to spare. */
@media (min-width: 1440px) {
  .rde-editor-ledger { flex-basis: 280px; }
}

/* ---- Editor simplification (2026-07-19): compact single-line section
   rows replacing the old always-fully-expanded per-section toolbar card
   (.rde-section-toolbar, above) — name+count on the left, keyboard-
   focusable reorder buttons + two contextual disclosures ("+ Новый
   вопрос" / "Ещё →") on the right, wrapping onto their own line at
   narrow widths instead of the whole row overflowing. ---------------- */
.tw-ws-section-row { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px 12px; padding: 8px 12px; border: 1px solid var(--gt-border); border-radius: var(--gt-radius-lg); margin-bottom: 8px; cursor: grab; }
/* Owner-caught (2026-07-23): with 3 flex children (handle/name/actions) and
   justify-content:space-between, the browser splits the row's free space
   into the two GAPS around the name — since the name's own text width
   differs per row, its left edge shifted per row ("jumping" text, not a
   consistent left-aligned column). flex:1 makes the name claim all
   leftover space itself, anchoring its left edge right after the handle
   on every row; the handle and actions block stay pinned to their edges. */
.tw-ws-section-row-name { flex: 1 1 auto; min-width: 0; font-weight: 600; }
.tw-ws-section-row-name small { color: var(--gt-text-muted); font-weight: 400; margin-left: 6px; }
.tw-ws-section-row-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.tw-ws-section-row-actions > details.tw-ws-more { margin-top: 0; }
.tw-ws-section-row-actions > details.tw-ws-more > summary { margin-top: 0; }
/* Row-icon correction (2026-07-23): the rename trigger is now a real
   gt-btn-icon SUMMARY (pencil svg, same component as the trash button
   beside it) instead of the bare-text "▸ Ещё" — strip the native
   disclosure marker and the inherited .tw-ws-more > summary text styling
   (color/font-size) that would otherwise fight the icon button's own. */
.tw-ws-rename-trigger { list-style: none; }
.tw-ws-rename-trigger > summary { list-style: none; color: inherit; font-size: inherit; }
.tw-ws-rename-trigger > summary::-webkit-details-marker,
.tw-ws-rename-trigger > summary::marker { display: none; content: none; }
/* Drag-to-reorder (2026-07-23, replaces the old ↑/↓ button pair): same
   is-dragging/is-drop-target convention already used by .tw-seq-row (the
   mechanic-order list on this same page) — opacity while lifted, an
   inset accent line showing where it will land. */
.tw-ws-drag-handle { color: var(--gt-text-muted); font-size: 16px; line-height: 1; padding: 0 2px; cursor: grab; user-select: none; }
.tw-ws-section-row.is-dragging { opacity: .45; }
.tw-ws-section-row.is-drop-target { box-shadow: inset 0 2px var(--gt-accent); }
.tw-ws-section-row:focus-visible { outline: none; box-shadow: var(--gt-focus-ring); }
/* Creation actions are equal peers: the frequent "+ Новый вопрос" comes
   first, "+ Новый раздел" follows beside it, and neither form occupies
   space until its control is opened. */
.tw-ws-create-bar { display: flex; align-items: flex-start; gap: 10px; flex-wrap: wrap; }
.tw-ws-create-action { flex: 0 0 auto; margin: 0; }
.tw-ws-create-action > summary.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 150px; margin: 0; list-style: none; box-sizing: border-box;
  padding: .45rem 1.1rem; color: white; font-size: 13.5px; font-weight: 600;
  line-height: normal;
}
.tw-ws-create-action > summary.btn::-webkit-details-marker { display: none; }
.tw-ws-create-action[open] { flex: 1 0 100%; }
.tw-ws-create-action[open] > summary.btn { margin-bottom: 10px; }
.tw-ws-create-action .tw-ws-more-body { max-width: 520px; }
.rde-rename-save[hidden] { display: none !important; }

/* ============================================================
   Owner-approved side-only desktop shell (2026-07-18): fixed left icon
   rail replaces the old top .header bar, matching the accepted reference's
   .gts-rail. THEME-AWARE (uses --gt-surface/--gt-border/--gt-accent, all
   already-existing, already switching tokens) — a deliberate, owner-
   approved supersession of DS-1C's earlier "shell stays always-dark"
   decision, scoped to the rail only. The old .header/.nav/.brand-label
   rules (further up this file) are now dead/unreferenced — left in place,
   byte-identical, matching the established "confirmed dead, left
   untouched" convention (.seed-info, the 6 former .rw-* rules, etc.).
   ============================================================ */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
/* Rail-correction stage (2026-07-22, contract 49415e9d53ea5aa9): owner
   corrected the width down to a compact 88px — nav destinations now stack
   icon-over-label (vertical hierarchy) instead of a horizontal icon+text
   row, so the rail no longer needs to be wide enough for the longest label
   text on one line. */
:root { --gt-rail-width: 88px; }
.gt-rail {
  position: fixed; top: 0; left: 0; bottom: 0; z-index: 50;
  display: flex; flex-direction: column; align-items: stretch;
  width: var(--gt-rail-width); padding: 12px 6px; gap: 16px;
  background: var(--gt-surface); border-right: 1px solid var(--gt-border);
}
.gt-rail-logo { display: flex; align-items: center; justify-content: center; }
/* Desktop-rail package (2026-07-21): the dark brand-surface chip was a
   workaround for ONE logo asset being illegible on the light theme. Now two
   real transparent-background theme variants exist (dark wordmark for
   Porcelain/light, white wordmark for Studio+Command/dark); each renders
   natively against the rail's own switching background, so no chip/
   background surface is needed at all. Exactly one <img> shows per theme —
   both are always in the DOM (no JS), toggled purely by body class. */
.gt-rail-logo-img-light { display: none; }
.theme-light .gt-rail-logo-img-dark { display: none; }
.theme-light .gt-rail-logo-img-light { display: block; }
/* Rail-correction stage (2026-07-22): the shared .brand-logo rule (height:
   32px, width:auto — used unchanged by mechanic pages and the frozen
   legacy web/nav.py render_global_nav(), NOT touched here) sizes the SAME
   wide wordmark asset (320x110px, ~2.91:1). At the corrected 88px rail
   width, the height is reduced from 24px to 18px (natural width 2.91 x 18
   = ~52.4px) so the logo clears the narrower rail with real margin on
   every configuration; flex-shrink:0 so the browser never silently
   compresses it (aspect-ratio distortion) instead of rendering its true
   intended size. */
.gt-rail-logo .brand-logo { height: 18px; flex-shrink: 0; }
.gt-rail-nav { display: flex; flex-direction: column; align-items: stretch; gap: 6px; flex: 1 1 auto; }
.gt-rail-bottom { display: flex; flex-direction: column; align-items: center; gap: 10px; }
/* Rail-correction stage (2026-07-22): base .gt-rail-link stays a simple
   centered flex box (row by default) — the toggle/account controls below
   use it as-is via their own compound overrides. Nav destinations get
   their OWN vertical icon-over-label layout, scoped to .gt-rail-nav only,
   so it never affects the toggle/account controls in .gt-rail-bottom. */
.gt-rail-link {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; height: 40px; padding: 0 12px; border: 0; border-radius: 10px;
  background: transparent; color: var(--gt-text-muted); cursor: pointer;
  text-decoration: none;
  transition: background .12s, color .12s;
}
.gt-rail-link svg { width: 20px; height: 20px; flex-shrink: 0; }
.gt-rail-link-label { font-size: 15px; font-weight: 600; white-space: nowrap; }
/* UI-002 fix (2026-07-22, #156): the global `a:hover, a:focus-visible {
   text-decoration: underline }` rule (this file, ~line 617) sets
   text-decoration on hover/focus for ANY <a> — since neither state below
   used to declare that property, the global rule's declaration won by
   default (per-property cascade, independent of these rules' own higher
   selector specificity for background/color). Every rail-link state now
   declares text-decoration: none explicitly, matching this file's existing
   R5/R6P-2 convention for button/pill-style links. */
.gt-rail-link:hover { background: var(--gt-accent-soft); color: var(--gt-text); text-decoration: none; }
.gt-rail-link:visited { text-decoration: none; }
.gt-rail-link.is-active { background: var(--gt-accent-soft); color: var(--gt-accent); text-decoration: none; }
/* INSPECTION-STANDALONE-VISUAL-DELIVERY-CLOSURE-01-CORRECTION-01: `--gt-focus-ring` is a COLOUR, not a shadow, so
   `box-shadow: var(--gt-focus-ring)` was invalid and dropped while `outline: none` removed the browser's own ring —
   Tab reached «Осмотры», the theme toggle and the account button and changed not one pixel. The translucent shared
   token alone was then measured at 2.1:1 against the rail in the dark theme and 1.4:1 in the light one, so the ring
   is a solid 2px line in the accent colour (7.6:1 and 6.8:1 on the rail surface) inside the usual soft halo. The logo
   link, the rail first stop, gets the same ring. */
.gt-rail-link:focus-visible,
.gt-rail-logo:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--gt-accent), 0 0 0 5px var(--gt-focus-ring); text-decoration: none; }
/* Rail-correction stage (2026-07-22): nav destinations stack icon ABOVE
   label (vertical hierarchy) instead of a horizontal icon+text row — the
   88px rail is too narrow for "Шаблоны"/"Осмотры" to sit beside their icon
   on one line. Scoped to .gt-rail-nav so the toggle/account controls
   (single-icon, no label) are unaffected. */
.gt-rail-nav .gt-rail-link {
  flex-direction: column; gap: 4px; height: auto; min-height: 52px; padding: 8px 2px;
}
.gt-rail-nav .gt-rail-link-label {
  font-size: 10px; line-height: 1.15; text-align: center; white-space: normal;
  max-width: 100%;
}
/* Rail-correction stage (2026-07-22): captionless toggle is now a 48x24
   clickable pill (not a 40x40 square badge) — border-radius:12px (=
   height/2) plus overflow:hidden clips the edge-to-edge sky-art SVG
   (.gt-theme-pill-art below) into a true pill silhouette.
   Owner-narrowed 2026-07-22: was 56x32; width reduced to 48 (owner
   request, "сузить немного").
   Owner-shortened 2026-07-22: was 48x32; height reduced to 24 (owner
   request, "уменьши высоту... без потери качества") — 24 is the measured
   floor: the sun icon's rays are the taller of the two artworks (visible
   content spans 18.8 local units), so 24 gives it a real, non-clipping
   ~2.6px margin top/bottom; the artwork's own line widths/radii are
   UNCHANGED (only the canvas/padding shrank), so nothing is rescaled or
   thinned — no loss of quality. See the SVG comments below for the exact
   bounding-box math. */
.gt-theme-toggle.gt-rail-link {
  width: 48px; height: 24px; padding: 0; justify-content: center;
  border-radius: 12px; overflow: hidden;
}
/* Specificity fix (2026-07-22, visual regression on top of e6b53f3): the
   generic `.gt-rail-link svg { width: 20px; height: 20px }` rule (above)
   has higher specificity (0,1,1) than a bare `.gt-theme-pill-art` (0,1,0)
   and applies to these SVGs too (they ARE `.gt-rail-link svg` descendants),
   so it silently won and clipped the full-pill artwork down to a 20x20
   icon inside the 56x32 button. Scoping to `.gt-theme-toggle` raises
   specificity to (0,2,0), which beats the generic icon rule without
   touching it (still correctly sizes every OTHER rail icon at 20x20) and
   without changing the button/rail geometry itself.
   `display: block` is deliberately NOT restated here (it was on the original
   bare rule) — at (0,2,0) it would now outrank `svg[hidden] { display: none }`
   (0,1,1) below and break the moon/sun hide/show toggle. The parent
   `.gt-theme-toggle` is a flex container, which blockifies its flex-item
   children regardless of their own `display` value, so omitting it here
   causes no layout change — verified live (art fills the full pill in both
   themes, and the hidden/visible toggle still works). Width/height must
   always match the button's own width/height exactly (viewBox + width/
   height in sync) — currently 48x24, see the button rule above for the
   owner-requested narrowing/shortening history. */
.gt-theme-toggle .gt-theme-pill-art { width: 48px; height: 24px; flex-shrink: 0; }
/* Live browser check (2026-07-21): Chromium's SVG UA stylesheet gives
   <svg> its own default `display: inline`, which wins over the HTML spec's
   `[hidden] { display: none }` rule at equal specificity — so a bare
   `hidden` attribute on an <svg> is silently ignored and BOTH the moon and
   sun badge rendered at once. An explicit rule is required for `hidden` to
   actually hide an <svg> in every browser. */
svg[hidden] { display: none; }
.gt-rail-link.gt-rail-user {
  width: 32px; height: 32px; padding: 0; justify-content: center;
  border-radius: 999px; background: var(--gt-surface-2); color: var(--gt-text-muted);
}
.gt-rail-user svg { width: 18px; height: 18px; }
/* Account menu payload: role block above the shared .gt-modal-actions
   logout button (existing convention, no new form wrapper class). The
   display NAME lives only in the shared modal's own title (set from
   data-modal-title by the generic dialog controller) — rail-correction
   stage (2026-07-22) removed the duplicate .gt-account-name rule/element
   so the name renders exactly once per open modal. */
.gt-account-identity { display: flex; flex-direction: column; gap: 2px; margin-bottom: 14px; }
.gt-account-role { font-size: 13px; color: var(--gt-text-muted); }
/* Offset page content past the fixed rail — a sibling combinator, not a
   class on <main>: only matches when .gt-rail actually renders (empty
   appheader on mechanic pages means no .gt-rail exists there at all, so
   mechanic pages get zero offset automatically, no per-route Jinja
   conditional needed). */
.gt-rail ~ main { margin-left: var(--gt-rail-width); }
/* 2K+ layout strategy (2026-07-22, owner-approved variant A): the board/
   list content deliberately stays capped at a comfortable reading width
   (see .ro-board-head/.ro-list/.ro-done above) rather than stretching into
   a sparse "sausage" — so the extra real estate on a 2K+ monitor goes to
   the one element that's genuinely vertical and benefits from more room:
   this rail. Above 1920px it grows from the compact 88px (icon-over-label,
   tuned for 1080p-ish screens) back to a horizontal icon+label row, which
   needs the extra width to fit "Шаблоны"/"Осмотры" on one line legibly. */
/* PATH08-RECEPTION-RESPONSIVE-BOARD-01 (2026-09-02): the mirror image of the
   2K rule below. The rail is `position: fixed` and every page's `<main>` is
   pushed past it by exactly its width, so on a 360px screen those 88px are a
   quarter of the entire usable width — permanently, on every desktop route.
   At phone widths the labels come off and the rail keeps only its icons, each
   of which already carries the same wording as its own `aria-label`, so the
   accessible name is unchanged and nothing becomes unreachable. */
@media (max-width: 640px) {
  :root { --gt-rail-width: 56px; }
  .gt-rail { padding: 10px 4px; gap: 10px; }
  .gt-rail-nav .gt-rail-link { min-height: 44px; padding: 6px 2px; }
  .gt-rail-nav .gt-rail-link-label { display: none; }
  .gt-rail-logo .brand-logo { height: 14px; }
}
@media (min-width: 1920px) {
  :root { --gt-rail-width: 176px; }
  .gt-rail-nav .gt-rail-link {
    flex-direction: row; justify-content: flex-start; gap: 12px;
    height: 40px; min-height: 40px; padding: 0 14px;
  }
  .gt-rail-nav .gt-rail-link-label {
    font-size: 13px; font-weight: 600; text-align: left; white-space: nowrap;
  }
  /* Owner-caught (2026-07-23): the logo stayed at its 18px narrow-rail
     size (52x18px) inside the now-doubled 176px rail — visibly lost/
     undersized next to the wider nav rows. Restored to the shared
     .brand-logo default (height: 32px, this file ~line 3667) — the exact
     size it was shrunk FROM for the 88px rail, so it's not a new number,
     just undoing that compression now that the rail has room again. */
  .gt-rail-logo .brand-logo { height: 32px; }
}

/* ============================================================
   TEMPLATE-WORKSPACE (2026-07-19): two-mode draft editor — "Структура по
   группам" (the existing progressive group→question→properties/phone
   editor) and "Порядок механика" (the independent global mechanic
   traversal order: drag + keyboard reorder, one explicit save). Prototype:
   docs/design-system/system-reference/template-workspace-sequence-prototype.html.
   Every rule reuses existing tokens only — no new color.
   ============================================================ */
.tw-modebar { display: flex; align-items: center; gap: 4px; margin: 18px 0 0; border-bottom: 1px solid var(--gt-border); }
.tw-mode { display: inline-flex; align-items: center; min-height: 38px; padding: 8px 14px; border: 0; border-radius: 8px 8px 0 0; background: transparent; color: var(--gt-text-muted); font-weight: 700; cursor: pointer; }
.tw-mode:hover { color: var(--gt-text); }
.tw-mode.is-active { background: var(--gt-surface-2); color: var(--gt-text); }
.tw-mode-panel[hidden] { display: none !important; }

/* Structure mode: give the existing editor equal-height panes (the
   prototype's fixed-height workbench). The ledger/properties panes already
   cap their own height and scroll internally.
   Live acceptance fix (2026-07-19): .rde-editor-rail's own base rule sets
   `align-self: flex-start` (its normal sticky-nav behavior elsewhere on the
   page), which overrides the parent's `align-items: stretch` for that one
   item — measured live, the rail's real bottom (1401px) sat 128.5px above
   the ledger/properties' shared bottom (1529.5px), the exact misalignment
   this stage fixes. Overriding align-self back to stretch (scoped to
   structure mode only) plus a matching max-height makes all three panels
   share the workbench's own 720px, each still scrolling internally via
   their existing overflow-y:auto — no new scroll mechanism invented. */
.tw-mode-panel[data-tw-mode-panel="structure"] .rde-editor-layout { height: 720px; align-items: stretch; }
.tw-mode-panel[data-tw-mode-panel="structure"] .rde-editor-rail { align-self: stretch; max-height: 720px; }
.tw-mode-panel[data-tw-mode-panel="structure"] .rde-editor-ledger,
.tw-mode-panel[data-tw-mode-panel="structure"] .rde-editor-properties,
.tw-mode-panel[data-tw-mode-panel="structure"] .rde-editor-preview { max-height: 720px; }

/* Mechanic-order sequence workbench — equal-height list + phone preview.
   Live-proven scroll fix (2026-07-19): grid-template-rows was never set on
   .tw-seq-workbench, so its single implicit row sized to CONTENT (auto),
   not the container's own 720px — measured live with real #156 data (156
   rows): .tw-seq-list-pane/.tw-seq-list/.tw-seq-preview all grew to
   8268px, .tw-seq-list's scrollHeight==clientHeight (nothing to scroll),
   row 156 sat at y=8953px, clipped away by the workbench's own
   overflow:hidden with no scroll mechanism to reach it. grid-template-rows:
   minmax(0, 1fr) forces the row to the container's real 720px; min-height:0
   on both column panes lets them actually shrink into it (grid items'
   automatic minimum size is otherwise their content size, the same class
   of bug already fixed once for .tw-seq-tag) — .tw-seq-list's own
   pre-existing min-height:0 + overflow-y:auto then becomes a REAL bounded
   scroll viewport. Workbench height (720px) and every other accepted
   fix from 2692d86 are unchanged. */
.tw-seq-workbench { display: grid; grid-template-columns: minmax(0, 1fr) minmax(320px, 400px); grid-template-rows: minmax(0, 1fr); height: 720px; margin-top: 12px; overflow: hidden; border: 1px solid var(--gt-border); border-radius: 12px; background: var(--gt-surface); }
.tw-seq-list-pane { display: grid; grid-template-rows: auto auto minmax(0, 1fr); min-width: 0; min-height: 0; border-right: 1px solid var(--gt-border); }
.tw-seq-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; padding: 14px 16px; border-bottom: 1px solid var(--gt-border); }
.tw-seq-head h2 { margin: 2px 0 4px; font-size: 19px; }
.tw-seq-head p { margin: 0; }
.tw-seq-actions { display: flex; align-items: center; gap: 10px; white-space: nowrap; }
.tw-seq-colhead, .tw-seq-row { display: grid; grid-template-columns: 34px 52px minmax(0, 1fr) minmax(120px, 200px) 74px; align-items: center; gap: 10px; }
.tw-seq-colhead { padding: 8px 16px; color: var(--gt-text-muted); font-size: 12px; border-bottom: 1px solid var(--gt-border); }
.tw-seq-list { min-height: 0; overflow-y: auto; }
.tw-seq-row { min-height: 52px; padding: 7px 16px; border-bottom: 1px solid var(--gt-border); background: transparent; color: var(--gt-text); text-align: left; cursor: grab; }
.tw-seq-row:hover, .tw-seq-row.is-selected { background: var(--gt-surface-2); }
.tw-seq-row.is-selected { box-shadow: inset 3px 0 var(--gt-accent); }
.tw-seq-row.is-dragging { opacity: .45; }
.tw-seq-row.is-drop-target { box-shadow: inset 0 2px var(--gt-accent); }
.tw-seq-row:focus-visible { outline: none; box-shadow: var(--gt-focus-ring); }
.tw-seq-handle { font-size: 19px; color: var(--gt-text-muted); cursor: grab; }
.tw-seq-step { font-weight: 800; font-variant-numeric: tabular-nums; }
.tw-seq-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Live acceptance fix (2026-07-19): a real section name ("Оборудование и
   предстартовая проверка", 37 chars) measured scrollWidth 223px against a
   clientWidth of 200px (the column's own max) — display:inline-flex has no
   overflow constraint, so the painted text spilled ~13px past the tag's own
   box into the ↑/↓ moves column 10px to its right, a real visual overlap.
   inline-block (not flex — text-overflow reliably ellipses on a plain
   inline/block box, not a flex container's own overflowing child text) +
   overflow:hidden/text-overflow:ellipsis/max-width:100% contains it inside
   the grid-stretched box; a title attribute keeps the full name reachable
   on hover. Grid's own align-items:center (unchanged) still centers it
   vertically; horizontal centering was cosmetic and not required. */
.tw-seq-tag { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; padding: 3px 9px; border-radius: 999px; background: var(--gt-surface-2); color: var(--gt-text-muted); font-size: 12px; font-weight: 700; white-space: nowrap; }
.tw-seq-moves { display: flex; gap: 4px; justify-content: flex-end; }
.tw-seq-mini { width: 30px; height: 30px; border: 1px solid var(--gt-border); border-radius: 7px; background: transparent; color: var(--gt-text); cursor: pointer; }
.tw-seq-mini:hover { border-color: var(--gt-accent); }
/* Visual finish pack (2026-07-22): the sequence row's keyboard-operable
   move controls now live behind a compact "Ещё" trigger (matching the
   tw-ws-more disclosure idiom used elsewhere in this same editor for
   section/question actions), instead of two always-visible buttons
   competing with the drag grip for attention in every row. */
.tw-seq-more { position: relative; list-style: none; }
.tw-seq-more > summary { list-style: none; display: flex; align-items: center; justify-content: center; }
.tw-seq-more > summary::-webkit-details-marker, .tw-seq-more > summary::marker { display: none; content: none; }
.tw-seq-more[open] > summary { border-color: var(--gt-accent); }
.tw-seq-more-body { position: absolute; right: 0; top: calc(100% + 4px); z-index: 5; display: flex; gap: 4px; padding: 4px; background: var(--gt-surface); border: 1px solid var(--gt-border); border-radius: 8px; box-shadow: var(--gt-shadow-md); }
.tw-seq-preview { display: grid; grid-template-rows: auto minmax(0, 1fr); min-width: 0; min-height: 0; background: var(--gt-surface-muted); }
.tw-seq-preview-body { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 16px; overflow-y: auto; }
.tw-seq-preview-body .rde-phone-frame { width: 300px; max-width: 100%; }
@media (max-width: 900px) {
  .tw-seq-workbench { grid-template-columns: 1fr; height: auto; }
  .tw-seq-preview { border-top: 1px solid var(--gt-border); }
  .tw-seq-colhead, .tw-seq-row { grid-template-columns: 28px 44px minmax(0, 1fr) 74px; }
  .tw-seq-tag { display: none; }
  .tw-mode-panel[data-tw-mode-panel="structure"] .rde-editor-layout { height: auto; }
}

/* ============================================================
   Template Workspace (2026-07-18): clean list, coherent draft editor,
   read-only mechanic phone preview. Every rule below is either an existing
   token (var(--gt-*)) or, for the phone preview, existing --mi-* tokens
   inherited from the reused .mech-app declaration (see .rde-phone-screen
   below) — no new color anywhere.
   ============================================================ */

/* ---- List page: row actions grouped into one aligned flex row (replaces
   the old scattered inline margin-left:10px per link/form). The table
   itself now sits inside a plain .gt-panel "workspace" container. -------- */
.tw-workspace-panel { padding: 0; overflow: hidden; }
.tw-workspace-panel > table { margin: 0; }
.tw-row-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.tw-row-actions form { display: inline; margin: 0; }

/* ---- Editor: compact one-line state indicator replacing the old two
   technical banners (.notice.neutral + .notice.warn). Reuses the SAME
   .gt-lifecycle-chip family the template list already renders. ---------- */
.tw-state-line { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* ---- Editor: name-save + publication grouped side by side under one
   heading instead of two separately-headed sections. ---------------------- */
/* Editor simplification (2026-07-19): align-items:flex-start left the two
   cards at their own natural (unequal) heights — the name-save card
   (label+input+button) and the publish card (meta text+button) rarely
   match. stretch equalizes both to the row's tallest card, a purely
   visual fix (no field/action/CSRF change). */
.tw-manage-row { display: flex; gap: 16px; flex-wrap: wrap; align-items: stretch; margin-top: 24px; }
.tw-manage-col { flex: 1 1 320px; min-width: 280px; margin: 0; }
/* Independently observed fix (2026-07-19): the #name input's OWN inline
   style="max-width:480px" (authored before .tw-manage-row existed, when
   this form spanned near-full page width) now caps it well below its own
   .tw-manage-col container's real available width (~570px+ at the
   approved 1440px review width) once grouped into the narrower two-
   column row — clipping the tail of long existing draft names (e.g.
   "... — черновик 2026-07-17 19:15:40" measured scrollWidth 490px vs a
   478px visible box, the trailing "40" scrolled out of view). templates/
   is outside this stage's authorized scope (style.css + scripts/checks/
   only), so the fix is a CSS override of the inline style; !important is
   required only because an inline style="" always outranks an external
   stylesheet rule otherwise — id="name" is unique across every template
   (verified), so this cannot affect any other field. Same width-fills-
   container approach already used for .rde-rename-input, no new cap. */
#name { max-width: 100% !important; }

/* ---- Editor: read-only phone-scale mechanic preview — standalone 4th
   pane (2026-07-19, 4-pane parity). One .rde-phone-preview per question,
   wrapped in a .rde-preview-card (only the current one displayed, see
   above); .rde-editor-preview is the scrolling pane, so the frame itself
   just fills the pane's own content width (up to a realistic phone-shape
   cap) instead of a small fixed sidebar size. ---------------------------*/
.rde-phone-preview { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.rde-phone-frame {
  width: 100%; max-width: 320px; border: 1px solid var(--gt-border); border-radius: 30px;
  padding: 8px; background: var(--gt-surface-2);
}
/* .mech-app's own rule (further up this file) sets full-page margin/
   min-height for the real mobile shell — both reset here for the small
   preview box. A 2-class selector beats the 1-class .mech-app rule on
   specificity alone, no !important needed; every --mi-* token declaration
   and the background/color/font-family .mech-app also sets still apply
   unchanged, so the preview uses the exact same palette as the real phone
   screen, not a re-invented one. */
.rde-phone-screen.mech-app {
  margin: 0; padding: 14px 12px 16px; min-height: auto;
  border-radius: 22px; overflow: hidden;
}
.rde-phone-screen .mech-q-card { margin-top: 0; }
.rde-phone-caption { color: var(--gt-text-muted); font-size: 11.5px; text-align: center; }

/* ============================================================
   TEMPLATE WORKSPACE — final visual package (2026-07-19)
   Progressive group→question→properties+phone editor + full iPhone frame,
   ported from docs/design-system/system-reference/template-workspace-
   sequence-prototype.html onto the GT design tokens (theme-aware in both
   desktop themes; the phone island keeps the real mechanic .mech-app
   --mi-* palette so it is faithful regardless of desktop theme). No new
   color literal except the phone's black dynamic island.
   ============================================================ */
/* Author display rules (.tw-ws-row{display:grid}, .btn{display:inline-flex})
   otherwise beat the UA [hidden] rule, so group-filtered question rows and
   the dirty-only save buttons would never hide. Restore [hidden] within the
   workspace surfaces explicitly. */
.tw-ws-workbench [hidden], .tw-manage-row [hidden], .tw-ws-toolbar [hidden] { display: none !important; }
.tw-ws-toolbar { display: flex; align-items: center; gap: 12px; margin-top: 12px; }
.tw-ws-expand { margin-left: auto; }
.tw-ws-back { min-width: 40px; padding: 6px 10px; font-weight: 700; flex: 0 0 auto; }
.tw-ws-workbench {
  display: grid; grid-template-rows: minmax(0, 1fr); height: 760px;
  margin-top: 10px; overflow: hidden;
  border: 1px solid var(--gt-border); border-radius: 12px; background: var(--gt-surface);
}
/* Progressive stages: reveal panes one at a time; at edit stage all four share
   the workbench's own single 760px row (grid stretch) with internal scroll. */
.tw-ws-workbench.tw-stage-groups {
  grid-template-columns: 1fr;
  height: auto; min-height: 0; max-height: min(620px, calc(100vh - 300px));
}
.tw-ws-workbench.tw-stage-groups .tw-ws-pane { height: auto; max-height: inherit; }
.tw-ws-workbench.tw-stage-groups .tw-ws-pane-body { max-height: calc(min(620px, calc(100vh - 300px)) - 52px); }
.tw-ws-workbench.tw-stage-questions { grid-template-columns: minmax(240px, .7fr) minmax(360px, 1.5fr); }
.tw-ws-workbench.tw-stage-edit { grid-template-columns: minmax(190px, .6fr) minmax(230px, .82fr) minmax(360px, 1.35fr) minmax(340px, 1.05fr); }
.tw-stage-groups .tw-ws-questions,
.tw-stage-groups .tw-ws-properties,
.tw-stage-groups .tw-ws-preview,
.tw-stage-questions .tw-ws-properties,
.tw-stage-questions .tw-ws-preview { display: none; }

.tw-ws-pane {
  display: grid; grid-template-rows: auto minmax(0, 1fr);
  min-width: 0; min-height: 0; height: 100%; overflow: hidden;
  border-right: 1px solid var(--gt-border); background: var(--gt-surface);
}
.tw-ws-pane:last-child { border-right: 0; }
.tw-ws-pane-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  min-width: 0; padding: 12px 14px; border-bottom: 1px solid var(--gt-border);
}
.tw-ws-pane-head > div { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.tw-ws-pane-head h2 { margin: 0; font-size: 18px; }
.tw-ws-preview-head { justify-content: center; text-align: center; }
.tw-ws-preview-head h2 { width: 100%; text-align: center; }
.tw-ws-step { color: var(--gt-text-muted); font-weight: 700; font-size: 12px; }
.tw-ws-head-actions { display: flex; align-items: center; gap: 8px; }
.tw-ws-pane-body { min-height: 0; overflow-y: auto; padding: 14px; }
.tw-ws-preview { background: var(--gt-surface-muted); }

.tw-ws-list { display: flex; flex-direction: column; }
.tw-ws-row {
  display: grid; grid-template-columns: 32px minmax(0, 1fr) auto; align-items: center; gap: 9px;
  width: 100%; min-height: 48px; padding: 9px 10px; border: 0; border-bottom: 1px solid var(--gt-border);
  background: transparent; color: var(--gt-text); text-align: left; cursor: pointer; font-size: 13.5px;
}
.tw-ws-row:hover { background: var(--gt-surface-2); }
.tw-ws-row.is-current { background: var(--gt-accent-soft); box-shadow: inset 3px 0 var(--gt-accent); }
.tw-ws-row b { color: var(--gt-text-muted); font-weight: 700; }
.tw-ws-row > span { min-width: 0; }
.tw-ws-group-row > span { white-space: normal; overflow-wrap: anywhere; }
.tw-ws-question-row > span { white-space: normal; }
.tw-ws-row small { color: var(--gt-text-muted); }
.tw-ws-search { width: 100%; margin-bottom: 6px; }
.tw-ws-qlist { margin-top: 8px; }

/* Only the current question's property card / phone card is shown. */
.tw-ws-properties .rde-question-card { display: none; }
.tw-ws-properties .rde-question-card.is-current { display: block; }
.tw-ws-more > summary { cursor: pointer; color: var(--gt-text-muted); font-size: 13px; margin-top: 6px; }
/* Editor simplification (2026-07-19): nested named collapsed groups inside
   "Продвинутые поля" (Мультивыбор/Уточнение/Категории) — same details/
   summary control, indented body so a nested group reads as a sub-section
   of the outer one, not a sibling. */
.rde-advanced-form > details.tw-ws-more { margin-top: 12px; }
.rde-advanced-form > details.tw-ws-more > summary { font-weight: 600; color: var(--gt-text); font-size: 14px; }
.tw-ws-more-body { margin: 10px 0 0 4px; padding-left: 10px; border-left: 2px solid var(--gt-border); display: flex; flex-direction: column; gap: 10px; }

/* ---- Full iPhone 16 Pro Max frame ---- */
.tw-ws-phone-stage { display: grid; place-items: start center; padding: 12px; gap: 8px; }
.tw-ws-phone-card { display: none; flex-direction: column; align-items: center; gap: 8px; width: 100%; }
.tw-ws-phone-card.is-current { display: flex; }
/* Live acceptance fix (2026-07-19): the sequence-mode workbench is 40px
   shorter than the structure-mode one (720px vs 760px, both pre-existing,
   accepted pane heights — untouched here), so the SAME phone-stage padding
   left 9px of unclipped overflow in .tw-seq-preview specifically (measured
   live: pane clientHeight 666px vs the phone+caption's 675px). A tighter
   stage padding here (not touched in structure mode) reclaims exactly that
   margin — the phone's own size/aspect is unchanged, still one component. */
.tw-seq-preview .tw-ws-phone-stage { padding: 8px; gap: 4px; }
.tw-ws-phone {
  /* Definite iPhone 16 Pro Max footprint (≈440:956). Fixed height so the
     frame holds its phone aspect regardless of question content length; the
     screen body scrolls internally when a long question overflows. */
  position: relative; flex: 0 0 auto; width: 288px; height: 626px; padding: 7px;
  border: 2px solid var(--gt-text); border-radius: 44px; background: var(--gt-surface-2);
  box-shadow: 0 18px 38px rgba(0, 0, 0, .28);
}
.tw-ws-phone-screen {
  position: relative; display: flex; flex-direction: column; height: 100%;
  overflow: hidden; border-radius: 38px;
}
/* Live acceptance fix (2026-07-19): .mech-app's OWN rule (full-page shell,
   further up this file) sets margin:-24px -28px / padding:18px 16px 28px /
   min-height:calc(100vh - 0px) — meant for the REAL full-viewport mechanic
   page. .tw-ws-phone-screen (equal specificity, single class) never
   overrode those three properties, so they fell through from .mech-app
   untouched: measured live, the screen box was 326x900px (min-height:
   100vh) inside a fixed 288x626px frame — 259px of unclipped overflow
   below the visible frame, the home indicator pushed off-screen, requiring
   page scroll to see the rest of the "device". A 2-class selector — the
   SAME pattern already used for .rde-phone-screen.mech-app above — resets
   exactly those three properties so the frame and screen genuinely share
   one set of bounds; every --mi-* token/background/color/font .mech-app
   also sets is untouched. Applies identically in structure mode
   (.tw-ws-phone-card) and sequence mode (.tw-seq-preview) — one complete
   phone component, one containment fix. */
.tw-ws-phone-screen.mech-app {
  margin: 0; padding: 0; min-height: auto;
}
.tw-ws-phone-island {
  position: absolute; top: 10px; left: 50%; z-index: 2; width: 33%; height: 22px;
  transform: translateX(-50%); border-radius: 16px; background: #050708;
}
.tw-ws-phone-status { display: flex; justify-content: space-between; padding: 12px 20px 4px; font-size: 12px; color: var(--mi-ink-soft); }
.tw-ws-phone-appbar {
  display: grid; grid-template-columns: 18px minmax(0, 1fr) auto; align-items: center; gap: 8px;
  padding: 10px 12px; border-top: 1px solid var(--mi-line); border-bottom: 1px solid var(--mi-line);
}
.tw-ws-phone-appbar > div { display: flex; flex-direction: column; min-width: 0; }
.tw-ws-phone-appbar b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.tw-ws-phone-appbar small { color: var(--mi-ink-faint); font-size: 11px; }
.tw-ws-phone-progress { height: 4px; background: var(--mi-surface-2); }
.tw-ws-phone-progress span { display: block; height: 100%; background: var(--mi-petrol); }
.tw-ws-phone-body { display: flex; flex: 1; flex-direction: column; gap: 10px; padding: 16px 14px; overflow-y: auto; overflow-x: hidden; min-width: 0; min-height: 0; }
.tw-ws-phone-body > * { min-width: 0; max-width: 100%; overflow-wrap: anywhere; }
.tw-ws-phone-q { font-size: 18px; margin: 4px 0; }
.tw-ws-answer-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 8px; }
.tw-ws-phone-req { margin-top: 6px; }
.tw-ws-phone-foot { margin-top: auto; }
.tw-ws-phone-nav { display: flex; justify-content: space-between; padding: 10px 14px; border-top: 1px solid var(--mi-line); color: var(--mi-ink-faint); font-size: 12.5px; }
.tw-ws-phone-home { width: 33%; height: 4px; margin: 6px auto 8px; border-radius: 4px; background: var(--mi-ink-faint); }

/* ---- Secondary structural-data menu (real sections, still editable) ---- */
.tw-ws-structure-menu { margin-top: 16px; padding: 12px 16px; }
.tw-ws-structure-menu > summary { cursor: pointer; font-weight: 700; }
.tw-ws-structure-body { margin-top: 12px; display: flex; flex-direction: column; gap: 12px; }
.tw-bulk-question-form { display: grid; grid-template-columns: minmax(180px, 1fr) minmax(160px, .7fr); gap: 10px; align-items: end; }
.tw-bulk-question-form label { display: grid; gap: 5px; }
.tw-bulk-question-copy { grid-column: 1 / -1; }
.tw-bulk-question-copy textarea { width: 100%; resize: vertical; }
.tw-blueprint-import { display: grid; gap: 10px; margin-top: 10px; }
.tw-publish-issues { max-height: 360px; overflow-y: auto; }
.tw-publish-issues ol { margin: 8px 0 0; padding-left: 24px; }

/* Template list: one stable information hierarchy instead of seven
   competing columns that repeated the same lifecycle state. */
/* Outer-contour correction (2026-07-21, owner-caught defect): every other
   .gt-panel workspace container clips its content to the panel's own
   rounded corners (overflow: hidden) — this one panel had overridden that
   to `visible`, so the table header's own smaller border-radius (10px,
   th:first-child/th:last-child) sat uncontained inside the panel's larger
   radius (18px), leaving a visible seam at both top corners instead of one
   continuous curve. `hidden` restores the same clean containment every
   other workspace panel already has. Nothing inside this panel needs
   overflow (the no-results banner and the shared modal both live OUTSIDE
   it as siblings; the filter <select>'s native popup is never affected by
   an ancestor's overflow). */
.tw-template-list-panel { padding: 0; overflow: hidden; width: 100%; }
.tw-template-table { table-layout: fixed; width: 100%; }
.tw-template-table th:nth-child(1) { width: 38%; }
.tw-template-table th:nth-child(2) { width: 23%; }
.tw-template-table th:nth-child(3) { width: 10%; }
/* Header-to-control alignment correction (2026-07-21, owner-caught defect):
   the actions cell right-aligns its action group, but the "Действия"
   header text was still left-aligned within the same column — the label
   floated far from the controls it names. Right-aligning the header puts
   it at the same column edge as every action group below it. */
.tw-template-table th:nth-child(4) { width: 29%; text-align: right; }
.tw-template-table td { vertical-align: middle; }
/* No-double-border correction (2026-07-21, owner-caught defect): every row
   drew its own bottom separator, including the LAST row — whose separator
   then sat immediately against the panel's own outer bottom border (a
   different color), reading as two stacked lines. Internal separators must
   stay strictly BETWEEN rows; the panel's own border is the sole bottom
   edge of the frame. */
.tw-template-table tbody tr:last-child td { border-bottom: none; }
.tw-template-identity strong { display: block; font-size: 15px; line-height: 1.35; }
/* Geometry correction (2026-07-21, owner-caught defect): the actions cell
   must right-align its action group so every row's group sits at the SAME
   right edge regardless of how many buttons that row's lifecycle state
   shows (a working row has more actions than a draft row) — `text-align`
   on the cell right-aligns the group's own inline-flex box without
   depending on its content width. (Previously this rule targeted the
   removed `.tw-row-actions` class and silently did nothing.) */
.tw-template-actions-cell { text-align: right; }
/* Template-list correction (2026-07-21): the fixed four-column table
   overlaps at 1024px, so the non-overlapping card layout must engage BEFORE
   that point — the breakpoint was 900px, which left 1024px broken. Each row
   becomes a block card; the action cluster stays left-aligned and wraps. */
@media (max-width: 1024px) {
  .tw-template-table thead { display: none; }
  .tw-template-table, .tw-template-table tbody, .tw-template-table tr, .tw-template-table td { display: block; width: 100%; }
  .tw-template-table tr { padding: 12px 14px; border-bottom: 1px solid var(--gt-border); }
  .tw-template-table td { padding: 5px 0; border: 0; }
  /* Right-aligned here too (not left, as an earlier stage had it): the
     required right-edge consistency spans every supported width, including
     this card breakpoint — a full-width card has no ergonomic reason to
     prefer left over right for a nowrap action cluster. */
}
@media (max-width: 900px) {
  .tw-bulk-question-form { grid-template-columns: 1fr; }
  .tw-bulk-question-copy { grid-column: auto; }
}

/* ════════════════════════════════════════════════════════════════════════
   GT component library v1 (2026-07-21, ADR 0020 DS-2). Centralized CSS for
   the Jinja macros in backend/app/web/components.html. Token-driven only (no
   new tokens, no raw hex); the accepted .btn family and DS-1B feedback
   selectors are untouched. text-decoration:none is enforced in EVERY .gt-btn
   state so an adopted anchor and button are visually identical.
   ════════════════════════════════════════════════════════════════════════ */
.gt-lifecycle-chip-previous { background: var(--gt-surface-2); color: var(--gt-text-muted); border: 1px solid var(--gt-border); }

/* ── Button/action: <a> and <button> identical through the API ─────────── */
.gt-btn,
.gt-btn:hover,
.gt-btn:focus,
.gt-btn:focus-visible,
.gt-btn:active,
.gt-btn:visited { text-decoration: none; }
.gt-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 34px; padding: 7px 12px; box-sizing: border-box;
  border: 1px solid transparent; border-radius: var(--gt-radius);
  font-family: inherit; font-size: 13px; font-weight: 700; line-height: 1.2;
  white-space: nowrap; cursor: pointer; width: auto;
  transition: background .15s, border-color .15s, box-shadow .15s, color .15s;
}
.gt-btn-primary { background: var(--gt-solid-accent-bg); color: #fff; border-color: transparent; }
.gt-btn-primary:hover { background: var(--gt-solid-accent-bg-hover); }
.gt-btn-ghost { background: transparent; color: var(--gt-text); border-color: var(--gt-field-border); }
.gt-btn-ghost:hover { background: var(--gt-surface-2); }
.gt-btn-danger.gt-btn-primary { background: var(--gt-danger); color: var(--gt-danger-solid-fg); }
.gt-btn-danger.gt-btn-primary:hover { background: var(--gt-danger); filter: brightness(0.94); }
.gt-btn-danger.gt-btn-ghost { color: var(--gt-danger); }
.gt-btn-danger.gt-btn-ghost:hover { background: var(--gt-danger-bg); border-color: var(--gt-danger); }
/* Owner request (2026-07-22): icon-only ghost buttons (the "i"/"trash"
   glyphs in action groups) must not carry a static resting-state outline
   — same "always do this for such buttons" durable rule as the size fix
   above, scoped to .gt-btn-icon (auto-applied to every icon-only button)
   combined with the ghost variant specifically, so labeled ghost buttons
   ("Отмена"/"Закрыть") keep their border for visual definition as a
   button.
   Owner correction (2026-07-23): the ORIGINAL version of this comment said
   hover states were deliberately untouched, including the danger-red
   hover border (.gt-btn-danger.gt-btn-ghost:hover sets border-color) — the
   owner caught that this still showed a highlighted ring around icon
   buttons (e.g. the trash icon) on hover and wants NONE, ever, on any
   icon-only ghost button in any state. The rule below now also covers
   :hover/:focus-visible/:active, at higher specificity than the danger
   hover rule above, so it wins regardless of variant. Labeled ghost
   buttons are unaffected (this is scoped to .gt-btn-icon only). */
.gt-btn-icon.gt-btn-ghost,
.gt-btn-icon.gt-btn-ghost:hover,
.gt-btn-icon.gt-btn-ghost:focus-visible,
.gt-btn-icon.gt-btn-ghost:active { border-color: transparent; }
.gt-btn:focus-visible { outline: none; box-shadow: var(--gt-interactive-focus-ring); }
.gt-btn:active { transform: translateY(1px); }
.gt-btn:disabled,
.gt-btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; pointer-events: none; }
.gt-btn.is-loading { opacity: .7; cursor: progress; pointer-events: none; }
/* Owner request (2026-07-22): "уменьшить эту кнопку на сколько это
   возможно и всегда так делать с такими кнопками в дальнейшем" — this is
   the ONE shared class gt_button auto-applies to every icon-only button
   (label='', icon set) app-wide, so shrinking it here is already the
   durable "always" rule, not a one-off. Floor is WCAG 2.5.8 (AA) 24x24 CSS
   px minimum target size — the icon itself is 16px (.gt-icon svg), so 4px
   padding on each side is the smallest size that still reads as a button
   (a border with visible breathing room) without dropping below the
   accessibility minimum. Base .gt-btn sets min-height:34px; overridden
   here down to 24px so icon-only buttons are truly 24x24, not 34x24. */
.gt-btn-icon { padding: 4px; width: 24px; min-height: 24px; }
/* Geometry correction (2026-07-21, owner-caught defect): the labeled
   PRIMARY action ("Копия" / "Активировать" / "Открыть" ...) must render at
   one identical width in every row regardless of label length, so the
   action group's shape is visually consistent down the whole list. Width
   is sized to the longest current label ("Активировать") plus buffer. */
.gt-action-group .gt-btn-primary:not(.gt-btn-icon) { min-width: 142px; }
.gt-icon { display: inline-flex; align-items: center; justify-content: center; }
.gt-icon svg { width: 16px; height: 16px; display: block; }
/* Misuse marker: an icon-only button with no accessible name — the adoption
   guard forbids this class from ever rendering. */
.gt-btn-missing-aria { outline: 2px dashed var(--gt-danger); }

/* ── Compact action group ──────────────────────────────────────────────── */
/* Geometry correction (2026-07-21, owner-caught defect): a compact action
   group is single-line by design (variant 3) — flex-wrap:wrap let a
   busier row silently wrap to a second line, giving that row a taller,
   inconsistent height/spacing versus its neighbors. nowrap keeps every
   row's action cluster on one line; the actions column and (in card mode)
   the full-width row always have enough room for the current action counts. */
.gt-action-group { display: inline-flex; flex-wrap: nowrap; align-items: center; justify-content: flex-end; gap: 8px; }
.gt-action-group-compact { gap: 3px; }
/* A POST action is a <form> wrapping a submit button; it must sit in the
   action row like any other button, not break onto its own block line. */
.gt-inline-form { display: inline-flex; margin: 0; }
.gt-action-group > form { display: inline-flex; margin: 0; }

/* ── Field / select (build on the global input/select rules) ───────────── */
.gt-field, .gt-select { min-height: 38px; }

/* ── Empty / no-results state (aria-live) ──────────────────────────────── */
.gt-empty-state {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  padding: 16px 18px; margin-top: 12px;
  border: 1px dashed var(--gt-border); border-radius: var(--gt-radius-md, 10px);
  background: var(--gt-surface-muted, var(--gt-surface-2)); color: var(--gt-text-muted);
}
.gt-empty-state[hidden] { display: none; }
.gt-empty-state-text { flex: 1 1 auto; }

/* ── Page header ───────────────────────────────────────────────────────── */
.gt-page-header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.gt-page-title { margin: 0; }
.gt-page-header-actions { display: inline-flex; align-items: center; gap: 8px; }

/* ── Управление (ADMIN-STAFF-MANAGEMENT-FOUNDATION-01, 2026-08-06) ───────
   Filter bar + a responsive staff table — collapses to one card per row
   below 900px (same technique as the template workspace's .tw-template-
   table), so the surface stays usable at a narrow viewport (Constitution
   §16.6 / this stage's acceptance). */
.mgmt-home-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px; margin-top: 18px; }
.mgmt-home-card { display: block; border: 1px solid var(--gt-border); border-radius: 14px; padding: 20px; text-decoration: none; color: inherit; background: var(--gt-surface); }
.mgmt-home-card:hover { border-color: var(--gt-accent); }
.mgmt-home-card h2 { margin: 0 0 6px; font-size: 17px; }
/* PATH08-MECHANIC-PIN-ONLY-DEVICE-TRUST-01: «Общие планшеты». The QR code stays dark on white in both
   themes — a camera reads contrast, not tokens — with a quiet zone of its own inside the SVG. */
.mgmt-tablet-qr { padding: 20px; margin: 16px 0; text-align: center; }
.mgmt-tablet-qr h2 { margin: 0 0 14px; font-size: 18px; }
.mgmt-tablet-qr-code { width: min(320px, 100%); margin: 0 auto 12px; background: #fff; border-radius: 10px; }
.mgmt-tablet-qr-code svg { display: block; width: 100%; height: auto; }
.mgmt-tablet-add { padding: 16px 20px; display: flex; flex-direction: column; gap: 8px; }
.mgmt-tablet-add label { font-weight: 600; }
.mgmt-tablet-add-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.mgmt-tablet-add-row input { flex: 1 1 220px; min-width: 0; }
.mgmt-tablet-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.mgmt-tablet-actions form { margin: 0; }
.mgmt-tablet-subtitle { margin: 24px 0 10px; font-size: 18px; }
.mgmt-tablet-note { margin: 12px 0 0; font-size: 14px; line-height: 1.45; color: var(--gt-text-muted); }
.mgmt-tablet-qr + .mgmt-panel, .mgmt-panel + .mgmt-panel { margin-top: 16px; }
.mgmt-home-card p { margin: 0; color: var(--gt-text-muted); font-size: 13.5px; }

.mgmt-filters { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 4px 0 18px; }
.mgmt-filters .gt-field { min-width: 220px; flex: 1 1 220px; }

.mgmt-panel { border: 1px solid var(--gt-border); border-radius: 14px; overflow: hidden; background: var(--gt-surface); }
.mgmt-table { width: 100%; border-collapse: collapse; }
.mgmt-table th, .mgmt-table td { padding: 10px 14px; text-align: left; border-bottom: 1px solid var(--gt-border); vertical-align: middle; }
.mgmt-table tbody tr:last-child td { border-bottom: none; }
.mgmt-table th { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--gt-text-muted); font-weight: 700; }
.mgmt-table-actions { text-align: right; }
.mgmt-phone-missing { color: var(--gt-status-draft-chip-fg); font-size: 12.5px; font-weight: 700; }
.mgmt-access-yes { color: var(--gt-result-all-clear-fg); font-weight: 600; }
.mgmt-access-no { color: var(--gt-text-muted); }
/* PATH02: the Полномочия cell — the Owner-granted authorities of a staff
   member, each with its own revoke form, plus one grant form per authority
   they do not hold. Rows stack vertically so the cell stays readable when a
   person holds both. */
.mgmt-authority-list { list-style: none; margin: 0 0 6px; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.mgmt-authority-list li { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; font-size: 13px; }
/* ---------------------------------------------------------------------------
   O2 / `OB-SEC-003` LIVE-UI-CORRECTION-01 (2026-08-18) — the Сотрудники list.

   THE DEFECT. «Вернуть доступ по PIN» is the only action in its row with a
   text label; every other action there is icon-only. With
   `.gt-action-group { flex-wrap: nowrap }` the cell demanded one long
   unbreakable line, the table grew wider than `.mgmt-panel`, and the panel
   clipped it: at 1249px an operator saw a key icon and the letter «В».
   Scrolling the table sideways showed the button but pushed the «Имя» column
   off screen, so the employee and the action on them were never readable at
   once — the operator could not tell WHO they were about to restore.

   WHY IT IS FIXED HERE AND NOT IN `.gt-action-group`. That class is shared by
   every action row in the product. Widening its behaviour globally to rescue
   one screen is how a local defect becomes a system-wide layout change nobody
   asked for. Everything below is scoped to `.mgmt-table-staff`.

   TWO RULES, IN ORDER OF WHAT THEY DO:

   1. the actions cell may WRAP. A second line inside the cell costs vertical
      space, which the page has; it removes the unbreakable minimum width,
      which the page does not have. Vertical growth is the acceptable
      direction — sideways scrolling is not, because it is exactly what
      separated the name from the action.

   2. below the width where the table genuinely fits, the list switches to the
      SAME card representation it already used under 900px. The boundary is
      MEASURED, not guessed, and it was moved once during this correction:
      1180px let the table survive by wrapping, but wrapping then applied to
      EVERY row — including ordinary ones with four icon-only actions that had
      always fitted on one line — and the whole list lost about half its
      density for the sake of one row. That is a worse screen, not a fixed
      one. The boundary now sits above the width at which the actions group
      genuinely fits on a single line (measured ~1380px with the worst
      realistic row: a person holding both authorities). Below it the card
      layout puts the name above its own actions, which satisfies the
      invariant by construction and reads better than a wrapped table.

      Rule 1 therefore almost never fires in table mode; it stays as the
      safety net for data slightly longer than today's.
--------------------------------------------------------------------------- */
.mgmt-table-staff .mgmt-table-actions .gt-action-group { flex-wrap: wrap; justify-content: flex-end; row-gap: 6px; }
/* The two icon-only lifecycle actions must not be squeezed to nothing when the
   labelled one wraps beside them. */
.mgmt-table-staff .mgmt-table-actions .gt-action-group > form { flex: 0 0 auto; }

@media (max-width: 1380px) {
  .mgmt-table-staff thead { display: none; }
  .mgmt-table-staff, .mgmt-table-staff tbody, .mgmt-table-staff tr, .mgmt-table-staff td { display: block; width: 100%; }
  .mgmt-table-staff tr { padding: 12px 14px; border-bottom: 1px solid var(--gt-border); }
  .mgmt-table-staff td { padding: 4px 0; border: 0; }
  .mgmt-table-staff td[data-label]::before { content: attr(data-label) ": "; font-weight: 700; color: var(--gt-text-muted); margin-right: 4px; }
  .mgmt-table-staff .mgmt-table-actions { text-align: left; margin-top: 8px; }
  .mgmt-table-staff .mgmt-table-actions .gt-action-group { justify-content: flex-start; }
}

@media (max-width: 900px) {
  .mgmt-table thead { display: none; }
  .mgmt-table, .mgmt-table tbody, .mgmt-table tr, .mgmt-table td { display: block; width: 100%; }
  .mgmt-table tr { padding: 12px 14px; border-bottom: 1px solid var(--gt-border); }
  .mgmt-table td { padding: 4px 0; border: 0; }
  .mgmt-table td[data-label]::before { content: attr(data-label) ": "; font-weight: 700; color: var(--gt-text-muted); margin-right: 4px; }
  .mgmt-table-actions { text-align: left; margin-top: 8px; }
}

.mgmt-form { max-width: 480px; display: flex; flex-direction: column; gap: 14px; margin-top: 12px; }
.mgmt-form label { display: flex; flex-direction: column; gap: 5px; font-size: 13.5px; font-weight: 600; color: var(--gt-text-muted); }
.mgmt-form input, .mgmt-form select, .mgmt-form textarea { min-height: 40px; border-radius: 10px; border: 1px solid var(--gt-field-border); padding: 8px 12px; font: inherit; background: var(--gt-surface); color: var(--gt-text); }
.mgmt-form textarea { min-height: 72px; resize: vertical; }
.mgmt-form-errors { border: 1px solid var(--gt-status-draft-chip-fg); background: var(--gt-status-draft-chip-bg); border-radius: 10px; padding: 10px 14px; margin: 4px 0; }
.mgmt-form-errors li { margin: 2px 0; }

.mgmt-history-facts { font-size: 12px; color: var(--gt-text-muted); font-family: monospace; word-break: break-all; }

/* PATH08-STAFF-ACCESS-ISSUANCE-01 (DC-SEC-022, DC-REL-029): the result of a staff
   action at the top of «Сотрудники» — who, their access, and the one next step.
   Theme tokens only, so it reads the same way in both desktop themes. */
.mgmt-result { display: flex; flex-direction: column; gap: 10px; max-width: 760px; margin: 4px 0 18px; padding: 16px 18px; border: 1px solid var(--gt-border); border-radius: 14px; background: var(--gt-surface); color: var(--gt-text); }
.mgmt-result-title { margin: 0; font-size: 18px; line-height: 1.3; font-weight: 700; color: var(--gt-text); }
.mgmt-result-text { margin: 0; line-height: 1.45; color: var(--gt-text); overflow-wrap: anywhere; }
.mgmt-result .gt-modal-list { margin: 0; }
.mgmt-result-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.mgmt-result-actions form { display: inline; margin: 0; }
.mgmt-result-confirm { border-color: var(--gt-state-danger-border, var(--gt-border)); }
.mgmt-access-code { margin: 0; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 28px; line-height: 1.2; font-weight: 700; letter-spacing: .08em; color: var(--gt-text); user-select: all; overflow-wrap: anywhere; }
.mgmt-access-pending { color: var(--gt-text); font-weight: 600; }

/* ── Accessible centered modal (shared dialog, controller in base.html) ── */
body.gt-modal-open { overflow: hidden; }
.gt-modal-overlay {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center; padding: 20px;
  background: rgba(15, 23, 42, 0.55);
}
.gt-modal-overlay[hidden] { display: none; }
.gt-modal {
  background: var(--gt-surface); color: var(--gt-text);
  border: 1px solid var(--gt-border); border-radius: var(--gt-radius-md, 10px);
  box-shadow: var(--gt-shadow-lg, 0 12px 40px rgba(0,0,0,0.3));
  width: 100%; max-width: 460px; max-height: calc(100vh - 40px); overflow: auto;
  padding: 20px 22px;
}
.gt-modal:focus { outline: none; }
.gt-modal-title { margin: 0 0 12px; font-size: 17px; line-height: 1.3; }
.gt-modal-list { margin: 0 0 16px; padding-left: 20px; display: flex; flex-direction: column; gap: 8px; }
.gt-modal-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; justify-content: flex-end; }
.gt-modal-actions form { display: inline; margin: 0; }

/* Consolidated correction (2026-07-20): blank-template guided first action —
   text + one primary CTA, replacing a text-only banner the author had to
   read then go search the page for the matching control themselves. */
.tw-ws-empty-state {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 16px; margin-bottom: 0.75rem; border: 1px solid var(--gt-border);
  border-radius: var(--gt-radius-md); background: var(--gt-surface-muted);
}
.tw-ws-empty-state-text { margin: 0; flex: 1 1 320px; color: var(--gt-text-muted); font-size: 0.9rem; line-height: 1.45; }
.tw-ws-empty-state .btn { flex: none; }
.tw-ws-addsection { display: flex; gap: 8px; align-items: center; }
.tw-ws-addsection input { flex: 1; max-width: 400px; }

@media (max-width: 1350px) {
  .tw-ws-workbench.tw-stage-edit { grid-template-columns: minmax(180px, .6fr) minmax(230px, .85fr) minmax(340px, 1.35fr); }
  .tw-ws-workbench.tw-stage-edit .tw-ws-preview { display: none; }
  /* Consolidated correction (2026-07-20): the phone preview must stay
     REACHABLE at this width, not just permanently hidden with no way back.
     The "Развернуть всё" toolbar toggle already exists and is wired in JS
     (adds/removes .tw-ws-open-all on the workbench) but had ZERO matching
     CSS anywhere — clicking it changed the button label with no visual
     effect. Wiring it here, scoped to THIS breakpoint only, stacks the
     preview back in as a full-width row below the 3-column edit stage —
     adaptive STACKING triggered by an explicit user toggle, not a bare
     display flip and not a forced 4-column squeeze. >=1350px is completely
     unaffected (.tw-ws-open-all still has no effect there, same as before —
     the accepted wide-screen four-pane layout is untouched). */
  .tw-ws-workbench.tw-stage-edit.tw-ws-open-all {
    height: auto;
    grid-template-rows: 460px auto;
  }
  .tw-ws-workbench.tw-stage-edit.tw-ws-open-all .tw-ws-preview {
    display: grid; grid-column: 1 / -1; grid-row: 2;
    border-top: 1px solid var(--gt-border); border-right: 0;
    max-height: 480px; overflow: auto;
  }
}
/* Login welcome motion concept — visual redo (2026-07-23, owner rejected
   the first pass live: "выглядит как ребёнок нарисовал" — canvas-drawn
   icon glyphs unrelated to their labels, monochrome pulses, unrecognizable
   car, side-by-side two-column layout). Replaced by ONE unified card
   matching an owner-supplied reference screenshot: brand mark + heading +
   the UNCHANGED form + the animated stage ring all live in one dark,
   elevated card — not spread across the page. */
/* Owner correction (2026-07-23): reverted the previous attempt at this
   gap (centering the card vertically) — the card belongs pinned to the
   TOP edge; the actual fix is making the ring/car POSITION ITSELF off
   the card's real bottom edge (see gt_login_welcome.js's layout(), which
   now reads .gt-login-card's own getBoundingClientRect() instead of a
   fixed 58%-of-viewport-height fraction) rather than moving the card to
   chase a fixed-position ring. */
/* Owner-caught (2026-07-23): "у меня в браузере баннер входа светлый, у
   тебя тёмный". The card followed the user's saved desktop theme, but the
   full-screen welcome layer the drop-in script paints is hard-coded dark
   (#0b0e13 canvas, light-on-dark tiles) and does NOT follow the theme — so
   a returning user whose last choice was Porcelain/light got a white card
   sitting on a black backdrop. The login screen is now deliberately
   theme-invariant: it re-declares the Studio (dark) token values for its
   own subtree only, so card, fields and button always match the backdrop.
   Nothing outside .gt-login-page is affected — the rest of the app still
   honours the toggle exactly as before. */
.gt-login-page {
  --gt-surface:       var(--gt-ref-studio-surface);
  --gt-surface-2:     var(--gt-ref-studio-surface-2);
  --gt-surface-muted: var(--gt-ref-studio-surface-muted);
  --gt-text:          var(--gt-ref-studio-text);
  --gt-text-muted:    var(--gt-ref-studio-text-muted);
  --gt-border:        var(--gt-ref-studio-border);
  --gt-accent:        var(--gt-ref-studio-accent);
  --gt-accent-hover:  color-mix(in srgb, var(--gt-ref-studio-accent) 85%, white);
  --gt-accent-soft:   var(--gt-ref-studio-accent-soft);
  --gt-danger:        var(--gt-ref-studio-danger);
  --gt-danger-bg:     var(--gt-ref-studio-danger-bg);
  /* Redeclaring the tokens is not enough on its own: `body` already
     resolved `color: var(--gt-text)` against the LIGHT palette, and colour
     inherits as a computed value, not as the variable. Without this line
     the heading and field labels kept Porcelain's near-black and vanished
     against the now-dark card (measured: h1 rgb(23,32,43) on a dark
     surface). Restating it here re-resolves it against the Studio tokens
     above and cascades to every descendant. */
  color: var(--gt-text);
  /* Column, not row: the tagline is a SECOND child under the card. As a row
     it would land beside the card instead of below it, and pull the card off
     the ring axis. justify-content stays at the start so the card keeps its
     top pinning (an explicit Owner requirement — never centre it vertically). */
  display: flex; flex-direction: column; justify-content: flex-start; align-items: center;
  /* Owner-caught (2026-07-23) "карточка должна быть ровно по центру оси
     кольца": min-height was calc(100vh - 40px), but the parent
     main.container adds 24px padding top AND bottom — so the page came out
     8px taller than the viewport (measured 1448 vs 1440), raising a
     vertical scrollbar. That scrollbar then narrowed the LAYOUT width
     while the canvas kept sizing itself to the full window width, so the
     card centred on one axis and the ring on another (~7.5px apart).
     Subtracting the real 48px removes the overflow, and the script now
     measures clientWidth instead of innerWidth so the two axes agree even
     if a scrollbar ever does appear. */
  /* Owner-caught on a real iPhone (2026-07-23), and his own diagnosis: the
     page was scrolling. On iOS 100vh is the LARGE viewport — the height with
     the URL bar hidden — so this box came out taller than what is actually on
     screen, the page scrolled, and the card slid under the fixed motion layer
     while the ring stayed put. svh is the SMALL viewport (URL bar shown),
     which is the height that is always really visible; the vh line stays
     first as the fallback for browsers without svh. */
  /* Its own fixed layer, pinned to the viewport, rather than a tall block
     inside a scrolling document. inset:0 bypasses main.container's 24px
     padding, so that 24px is added back here to keep the card exactly where
     it already sat (measured: cardTop 82 at 2560x1440, 48 at 440x796 — the
     same before and after this change). */
  position: fixed;
  inset: 0;
  z-index: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  min-height: 0;
  /* Padding in svh, not vh, for the same reason as the min-height: vh tracks
     the LARGE viewport, so on iOS it changes as the URL bar collapses — and
     since the whole scene is anchored to the card's bottom edge, a card that
     drifts drags the ring and every badge with it. That is the "элементы
     расползаются когда трогаешь". svh does not move. */
  /* --gt-login-host-pad restores whatever vertical padding main.container
     used to contribute, which is 24px on desktop and 16px at phone widths
     (see the media query at the end of this file). Without it the card jumps
     when the page becomes a fixed layer. */
  --gt-login-host-pad: 24px;
  padding: calc(4vh + var(--gt-login-host-pad)) var(--gt-space-4) calc(3vh + var(--gt-login-host-pad));
  padding: calc(4svh + var(--gt-login-host-pad)) var(--gt-space-4) calc(3svh + var(--gt-login-host-pad));
}
/* Owner correction (2026-07-23): "сам баннер входа избыточно большой" —
   tightened from 480px/32-28px padding/24px radius down to 392px and a
   compact padding scale. This also directly buys vertical room for the
   ring + stage badges below it, which are sized against whatever space
   the card leaves (see ringMetrics() in gt_login_welcome.js). */
/* Owner request (2026-07-23): "свечение от кольца должно мягко снизу
   вверх распространяться по баннеру входа на заднем плане". Done with two
   cooperating layers rather than a painted-on gradient alone, so the light
   genuinely comes FROM the ring:
     1. The card's own surface fades toward transparent at the BOTTOM, and
        backdrop-filter blurs whatever is behind it — so the canvas halo
        the ring actually paints (gt_login_welcome.js's drawRingAndConnectors)
        shines up THROUGH the lower part of the card. Because that halo is
        tinted with the current car's colour, the card's underglow shifts
        colour with it for free.
     2. ::after adds a soft bottom-anchored wash in the SAME live colour
        (--gt-login-glow, republished each cycle by the script, falling back
        to brand red) so the effect still reads on browsers without
        backdrop-filter, and stays legible over the blur.
   Opacity is kept high enough at the top that the heading/fields never
   lose contrast — the fade only really opens up below the submit button. */
/* Staff feedback (2026-07-23): the motion read as decoration — nobody could
   say what it meant. One line under the card names the idea the badges and the
   car already show, so the scene explains itself without extra UI. */
.gt-login-tagline {
  /* The motion canvas is a fixed layer painted above static content: without
     its own stacking context this line renders but stays invisible behind it
     (the card carries one for the same reason). */
  position: relative;
  z-index: 3;
  margin: 16px auto 0;
  /* Wider than the card on purpose: at the card's own 392px this sentence
     wrapped to two lines on desktop. It still wraps on phones, which is
     correct there. */
  max-width: min(560px, 92vw);
  text-align: center;
  font-size: 13px;
  line-height: 1.45;
  color: color-mix(in srgb, var(--gt-ref-studio-text-muted) 88%, transparent);
}
/* Short phones fit the card + this line + the ring + two badge rows only if
   the spacing gives way; tightened here rather than dropping any of them. */
@media (max-height: 700px) {
  .gt-login-tagline { margin-top: 9px; font-size: 12px; }
}

.gt-login-card {
  --gt-login-glow: var(--gt-brand-red);
  position: relative; width: 100%; max-width: 460px;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--gt-surface) 97%, transparent) 0%,
    color-mix(in srgb, var(--gt-surface) 93%, transparent) 40%,
    color-mix(in srgb, var(--gt-surface) 80%, transparent) 72%,
    color-mix(in srgb, var(--gt-surface) 64%, transparent) 100%);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid var(--gt-border); border-radius: 18px;
  padding: 22px 22px 20px; overflow: hidden;
  box-shadow: 0 24px 64px -22px rgba(0,0,0,.55), var(--gt-shadow-md);
}
/* Thin lit edge along the bottom rim — the "light lands here" cue that
   makes the glow read as coming from below rather than being painted on. */
.gt-login-card::before {
  content: ""; position: absolute; left: 14%; right: 14%; bottom: 0; height: 1px;
  background: linear-gradient(90deg, transparent,
    color-mix(in srgb, var(--gt-login-glow) 60%, transparent), transparent);
  pointer-events: none; z-index: 0;
}
/* The rising wash itself: anchored to the bottom edge, widest there,
   dissolving well before the form fields. */
.gt-login-card::after {
  content: ""; position: absolute; left: 50%; bottom: -16%; width: 160%; height: 96%;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at 50% 100%,
    color-mix(in srgb, var(--gt-login-glow) 22%, transparent) 0%,
    color-mix(in srgb, var(--gt-login-glow) 11%, transparent) 28%,
    color-mix(in srgb, var(--gt-login-glow) 4%, transparent) 55%,
    transparent 80%);
  pointer-events: none; z-index: 0;
  transition: background 900ms ease;
}
/* Owner correction (2026-07-23): the login card had grown a SECOND,
   redundant "GT SERVICE" text label next to the logo image — the
   existing brand-logo PNG (same file/sizing convention as .gt-rail-logo
   in base.html) already carries the wordmark baked in, so pairing it
   with a duplicate text span read as a mismatched/unfamiliar lockup
   ("не тот логотип"). Now just the image, matching the rail's own
   "image speaks for itself" pattern exactly. */
.gt-login-brand { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; margin-bottom: 16px; }
/* Owner-caught (2026-07-23): "логотип посмотри, не читается текст". These
   rules were INVERTED against the rail's working ones (style.css ~3685):
   the *-dark asset is the WHITE wordmark meant FOR a dark surface, but this
   block hid it by default and showed it only under .theme-light — i.e.
   dark-on-dark in the default theme and white-on-white in the light one.
   Both were unreadable. Since the login card is now theme-invariant dark
   (see .gt-login-page above), the correct answer is simply: always the
   white/dark-surface asset, never the light-surface one. */
.gt-login-brand-img { height: 36px; flex-shrink: 0; }
.gt-login-brand-img-dark { display: block; }
.gt-login-brand-img-light { display: none; }
.theme-light .gt-login-brand-img-dark { display: block; }
.theme-light .gt-login-brand-img-light { display: none; }
.gt-login-shell { position: relative; z-index: 1; }
.gt-login-shell .wo-list-header { border-bottom: 0; margin-bottom: var(--gt-space-4); padding-bottom: 0; justify-content: center; text-align: center; }
.gt-login-shell .wo-list-header h1 { font-size: 20px; }
.gt-login-subtitle { margin: 3px 0 0; font-size: 12px; color: var(--gt-text-muted); }
/* Compact form metrics inside the smaller card — the fields keep their
   own shared component styling, only the vertical rhythm tightens. */
.gt-login-shell .form-row { margin-bottom: 12px; }
.gt-login-shell .form-row label { font-size: 15px; margin-bottom: 6px; }
.gt-login-shell input[type="text"],
.gt-login-shell input[type="password"] { min-height: 46px; padding-top: 8px; padding-bottom: 8px; font-size: 17px; }
/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-FIDELITY-01 (accepted 2026-09-19, portion 3): card 460, labels 15, fields 17,
   a larger logo, stage labels 13 and lighter; the animation itself is untouched («мне нравиться»). */
.gt-login-shell .btn-primary:hover { background: var(--gt-accent-hover); }
.gt-login-shell .btn-primary { min-height: 40px; padding-top: 9px; padding-bottom: 9px; }
.gt-login-shell .gt-panel { max-width: none; background: transparent; border: 0; box-shadow: none; padding: 0; }

/* The animated stage ring — six real DOM badges (crisp SVG icon + real
   label text, positioned by gt_login_welcome.js via inline left/top %)
   around a canvas that draws ONLY the decorative ring/pulses/sedan
   reveal. aspect-ratio keeps the ring circular-reading across widths;
   verified live at 1024/1440/1715px, both themes. */
.gt-login-visual { position: relative; z-index: 1; margin-top: 26px; aspect-ratio: 1 / 0.86; }
.gt-login-canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
.gt-login-badge {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center; gap: 5px; width: 76px;
  transition: transform .15s ease;
}
.gt-login-badge.is-active { transform: translate(-50%, -50%) scale(1.08); }
.gt-login-badge-icon {
  --badge-c: var(--gt-accent);
  width: 42px; height: 42px; border-radius: 13px; display: flex; align-items: center; justify-content: center;
  color: var(--badge-c);
  background: linear-gradient(160deg, color-mix(in srgb, var(--badge-c) 20%, var(--gt-surface)), color-mix(in srgb, var(--badge-c) 9%, var(--gt-surface)));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--badge-c) 45%, transparent), inset 0 1px 0 color-mix(in srgb, white 10%, transparent), 0 3px 8px -3px rgba(0,0,0,.5);
  transition: box-shadow .15s ease, transform .15s ease;
}
.gt-login-badge.is-active .gt-login-badge-icon { box-shadow: inset 0 0 0 1.5px var(--badge-c), 0 0 0 4px color-mix(in srgb, var(--badge-c) 22%, transparent), 0 3px 8px -3px rgba(0,0,0,.5); }
.gt-login-badge-icon .gt-icon svg { width: 21px; height: 21px; }
.gt-login-badge-label { font-size: 13px; font-weight: 600; color: color-mix(in srgb, var(--gt-text) 82%, var(--gt-text-muted)); text-align: center; line-height: 1.15; }

@media (max-width: 900px) {
  .tw-ws-workbench { height: auto; grid-template-columns: 1fr !important; }
  .tw-ws-pane { min-height: 460px; border-right: 0; border-bottom: 1px solid var(--gt-border); }
  .tw-stage-groups .tw-ws-questions,
  .tw-stage-groups .tw-ws-properties,
  .tw-stage-groups .tw-ws-preview,
  .tw-stage-questions .tw-ws-properties,
  .tw-stage-questions .tw-ws-preview { display: grid; }
}

/* Owner (2026-07-23): "карточка входа на телефоне выглядит слишком большой".
   Measured at 440x796 it was 352px — 44% of the screen — because it carries
   desktop padding and type on a phone. Trimmed to the parts that actually
   cost height (padding, heading size, the gaps around the header and between
   fields), leaving the fields themselves at a comfortable 38px tap target. */
/* iOS rubber-band: the page does not actually scroll (measured SCROLLABLE 0
   on the device), but a swipe still bounces it. The card rides the bounce
   while the motion layer is position:fixed and does not — so the two visibly
   come apart mid-gesture. Refusing the overscroll is what stops it; there is
   nothing to scroll to, so nothing is lost. */
/* Scoped by a class the login script sets, NOT by :has(): :has() needs
   Chrome 105+/Safari 15.4+, and this app is opened on shop Android phones
   whose browser may be older. A class works everywhere. */
/* overscroll-behavior alone did not hold on the device: the Owner still saw
   the page move AND the motion layer shift relative to the card. So the login
   screen stops being a scrollable document at all — html/body are locked to
   the viewport and .gt-login-page becomes its own fixed full-screen layer
   (see below). With no document scroll there is nothing to rubber-band, and
   the card can no longer travel while the fixed canvas stays put.
   Two selector forms on purpose: the class is set by the script and reaches
   older Android engines; :has() applies from the very first style pass,
   before any script has run. */
html.gt-login-nobounce, html.gt-login-nobounce body,
html:has(.gt-login-page), body:has(.gt-login-page) {
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
}

@media (max-width: 560px) {
  .gt-login-page { --gt-login-host-pad: 16px; }
  .gt-login-card { padding: 15px 16px 14px; border-radius: 16px; }
  .gt-login-brand { margin-bottom: 6px; }
  .gt-login-shell .wo-list-header { margin-bottom: 10px; gap: 2px; }
  .gt-login-shell .wo-list-header h1 { font-size: 21px; line-height: 1.2; }
  .gt-login-subtitle { font-size: 12px; }
  .gt-login-shell .form-row { margin-bottom: 9px; }
  .gt-login-shell label { font-size: 12px; }
  .gt-login-shell input[type="text"],
  .gt-login-shell input[type="password"] { min-height: 38px; }
  .gt-login-shell .btn-primary { min-height: 38px; }
}


/* ═══ S5 suspension cards — canonical card CSS ══════════════════════════════
   Every one of the 12 owner-accepted suspension cards used to ship its own
   <style> block inside templates/partials/suspension_cards.html. Owner rule
   (S5 mobile visual review, 2026-07-25): all visual behavior must be carried
   by the shared design pack, so those blocks were MOVED here verbatim —
   declaration for declaration, in card order, still id-scoped to that card's
   own #gt-... section, which is why nothing here can reach any other surface.
   The token names they consume (--card, --muted, --viz-series-N, --space-N)
   are aliased to the real mechanic tokens by the .mech-app bridge above.
   Source of truth: accepted-suspension-cards/*.html at the 2026-07-25 owner
   correction; equality is re-derived by
   scripts/ops/verify_suspension_s5_selector.py --canonical-integrity.
   Do not hand-edit: re-extract from the canonical sources instead. */

/* --- front-macpherson-single-lower-arm-v1 --- canonical card CSS, verbatim from accepted-suspension-cards/front-macpherson-single-lower-arm-v1.html --- */
  #gt-accepted-macpherson-single-arm-v1 .gt-card-stack {
    display: grid;
    gap: var(--space-4, 16px);
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-diagram {
    display: block;
    width: 100%;
    height: auto;
    color: var(--card-foreground);
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-wheel {
    fill: var(--muted-foreground);
    stroke: var(--foreground);
    stroke-width: 5;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-sidewall {
    fill: none;
    stroke: var(--border);
    stroke-width: 4;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-rim {
    fill: var(--card);
    stroke: var(--muted);
    stroke-width: 10;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-brake-disc {
    fill: var(--muted);
    stroke: var(--muted-foreground);
    stroke-width: 4;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-spoke {
    stroke: var(--muted-foreground);
    stroke-width: 17;
    stroke-linecap: round;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-caliper {
    fill: var(--viz-series-5);
    stroke: var(--card);
    stroke-width: 3;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-hub {
    fill: var(--card);
    stroke: var(--foreground);
    stroke-width: 6;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-chassis {
    stroke: var(--muted-foreground);
    stroke-width: 10;
    stroke-linecap: round;
    fill: none;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-upright {
    stroke: var(--foreground);
    stroke-width: 18;
    stroke-linecap: round;
    fill: none;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-arm {
    stroke: var(--viz-series-1);
    stroke-width: 13;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: color-mix(in srgb, var(--viz-series-1) 10%, transparent);
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-upper-arm {
    stroke: var(--viz-series-6);
    fill: color-mix(in srgb, var(--viz-series-6) 10%, transparent);
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-damper {
    stroke: var(--viz-series-2);
    stroke-width: 15;
    stroke-linecap: round;
    fill: none;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-spring {
    stroke: var(--viz-series-2);
    stroke-width: 5;
    fill: none;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-steering {
    stroke: var(--viz-series-3);
    stroke-width: 9;
    stroke-linecap: round;
    fill: none;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-stabilizer {
    stroke: var(--viz-series-4);
    stroke-width: 10;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-drop-link {
    stroke: var(--viz-series-5);
    stroke-width: 11;
    stroke-linecap: round;
    fill: none;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-drop-link-bracket {
    stroke: var(--viz-series-5);
    stroke-width: 9;
    stroke-linecap: round;
    fill: none;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-joint {
    fill: var(--card);
    stroke: var(--foreground);
    stroke-width: 4;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-mount {
    fill: var(--muted);
    stroke: var(--muted-foreground);
    stroke-width: 3;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-top-mount-plate {
    fill: var(--muted);
    stroke: var(--viz-series-6);
    stroke-width: 4;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-top-mount-bearing {
    fill: var(--card);
    stroke: var(--viz-series-6);
    stroke-width: 5;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-marker {
    fill: var(--primary);
    stroke: var(--primary-foreground);
    stroke-width: 2;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-marker-text {
    fill: var(--primary-foreground);
    font-weight: 500;
    text-anchor: middle;
    dominant-baseline: central;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-card-copy {
    display: grid;
    gap: var(--space-3, 12px);
    grid-column: 1;
    grid-row: 1;
    min-width: 0;
  }

  #gt-accepted-macpherson-single-arm-v1 article {
    display: grid;
    grid-template-columns: minmax(240px, .8fr) minmax(0, 1.6fr);
    gap: var(--space-4, 16px);
    align-items: start;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-diagram {
    grid-column: 2;
    grid-row: 1;
    width: 100%;
    height: auto;
    shape-rendering: geometricPrecision;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-diagram path,
  #gt-accepted-macpherson-single-arm-v1 .gt-diagram line,
  #gt-accepted-macpherson-single-arm-v1 .gt-diagram polyline {
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-card-copy h3,
  #gt-accepted-macpherson-single-arm-v1 .gt-card-copy p {
    margin: 0;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-legend {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-2, 8px);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-legend li {
    display: flex;
    gap: var(--space-2, 8px);
    align-items: baseline;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-legend li > span:last-child {
    min-width: 0;
    overflow-wrap: break-word;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-legend b {
    font-weight: 500;
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-swatch {
    inline-size: 12px;
    block-size: 12px;
    flex: 0 0 12px;
    border-radius: 50%;
    background: var(--muted-foreground);
  }

  #gt-accepted-macpherson-single-arm-v1 .gt-key-mount { background: var(--viz-series-6); }
  #gt-accepted-macpherson-single-arm-v1 .gt-key-damper { background: var(--viz-series-2); }
  #gt-accepted-macpherson-single-arm-v1 .gt-key-wheel { background: var(--muted-foreground); }
  #gt-accepted-macpherson-single-arm-v1 .gt-key-upright { background: var(--foreground); }
  #gt-accepted-macpherson-single-arm-v1 .gt-key-steering { background: var(--viz-series-3); }
  #gt-accepted-macpherson-single-arm-v1 .gt-key-drop-link { background: var(--viz-series-5); }
  #gt-accepted-macpherson-single-arm-v1 .gt-key-lower-arm { background: var(--viz-series-1); }
  #gt-accepted-macpherson-single-arm-v1 .gt-key-upper-arm { background: var(--viz-series-6); }
  #gt-accepted-macpherson-single-arm-v1 .gt-key-stabilizer { background: var(--viz-series-4); }

  @media (max-width: 560px) {
    #gt-accepted-macpherson-single-arm-v1 article {
      grid-template-columns: 1fr;
    }

    #gt-accepted-macpherson-single-arm-v1 .gt-card-copy,
    #gt-accepted-macpherson-single-arm-v1 .gt-diagram {
      grid-column: 1;
      grid-row: auto;
    }

    #gt-accepted-macpherson-single-arm-v1 .gt-legend {
      grid-template-columns: 1fr;
    }
  }
  @media (max-width: 719px) {
    #gt-accepted-macpherson-single-arm-v1 article.card {
      display: grid;
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-3, 12px);
      align-items: start;
    }

    #gt-accepted-macpherson-single-arm-v1 .gt-card-copy {
      display: contents;
    }

    #gt-accepted-macpherson-single-arm-v1 .gt-card-copy > h3 { order: 1; }
    #gt-accepted-macpherson-single-arm-v1 .gt-card-copy > p { order: 2; }
    #gt-accepted-macpherson-single-arm-v1 .gt-diagram {
      order: 3;
      width: 100%;
      min-width: 0;
      max-height: none;
    }
    #gt-accepted-macpherson-single-arm-v1 .gt-card-copy > .gt-legend { order: 4; }
  }

/* --- front-macpherson-two-lower-arms-v1 --- canonical card CSS, verbatim from accepted-suspension-cards/front-macpherson-two-lower-arms-v1.html --- */
  /* Owner-corrected geometry: preserve the 3/4 view and attachment points; show the subframe as an open cradle, not a filled box. */
  #gt-double-ball-macpherson-v3 .gt-layout{display:grid;grid-template-columns:minmax(240px,.8fr) minmax(0,1.6fr);gap:var(--space-4,16px);align-items:start}
  #gt-double-ball-macpherson-v3 .gt-copy{display:grid;gap:var(--space-3,12px)}
  #gt-double-ball-macpherson-v3 h3,#gt-double-ball-macpherson-v3 p{margin:0}
  #gt-double-ball-macpherson-v3 .gt-count{color:var(--muted-foreground);font-weight:500}
  #gt-double-ball-macpherson-v3 .gt-diagram{display:block;width:100%;height:auto;color:var(--card-foreground)}
  #gt-double-ball-macpherson-v3 .gt-separator{stroke:var(--border);stroke-width:2}
  #gt-double-ball-macpherson-v3 .gt-body{fill:none;stroke:var(--muted-foreground);stroke-width:10;stroke-linecap:round}
  #gt-double-ball-macpherson-v3 .gt-subframe{fill:none;stroke:var(--muted-foreground);stroke-width:16;stroke-linecap:round;stroke-linejoin:round;opacity:.72}
  #gt-double-ball-macpherson-v3 .gt-wheel-guide{fill:none;stroke:var(--muted-foreground);stroke-width:12;opacity:.34}
  #gt-double-ball-macpherson-v3 .gt-wheel-inner{fill:none;stroke:var(--muted-foreground);stroke-width:4;opacity:.28}
  #gt-double-ball-macpherson-v3 .gt-knuckle{fill:color-mix(in srgb,var(--foreground) 14%,var(--card));stroke:var(--foreground);stroke-width:9;stroke-linejoin:round}
  #gt-double-ball-macpherson-v3 .gt-hub{fill:var(--card);stroke:var(--foreground);stroke-width:8}
  #gt-double-ball-macpherson-v3 .gt-lateral{fill:color-mix(in srgb,var(--viz-series-1) 25%,transparent);stroke:var(--viz-series-1);stroke-width:9;stroke-linejoin:round}
  #gt-double-ball-macpherson-v3 .gt-tension{fill:color-mix(in srgb,var(--viz-series-3) 22%,transparent);stroke:var(--viz-series-3);stroke-width:9;stroke-linejoin:round}
  #gt-double-ball-macpherson-v3 .gt-strut{fill:none;stroke:var(--viz-series-5);stroke-width:26;stroke-linecap:round}
  #gt-double-ball-macpherson-v3 .gt-rod{fill:none;stroke:var(--viz-series-5);stroke-width:10;stroke-linecap:round}
  #gt-double-ball-macpherson-v3 .gt-spring-coil{fill:none;stroke:var(--viz-series-2);stroke-width:7}
  #gt-double-ball-macpherson-v3 .gt-spring-seat{fill:none;stroke:var(--viz-series-2);stroke-width:8}
  #gt-double-ball-macpherson-v3 .gt-top-mount{fill:color-mix(in srgb,var(--viz-series-6) 28%,var(--card));stroke:var(--viz-series-6);stroke-width:8}
  #gt-double-ball-macpherson-v3 .gt-stabilizer{fill:none;stroke:var(--destructive);stroke-width:12;stroke-linecap:round;stroke-linejoin:round}
  #gt-double-ball-macpherson-v3 .gt-stab-link{fill:none;stroke:var(--viz-series-4);stroke-width:12;stroke-linecap:round}
  #gt-double-ball-macpherson-v3 .gt-joint,#gt-double-ball-macpherson-v3 .gt-mount{fill:var(--card);stroke-width:5}
  #gt-double-ball-macpherson-v3 .gt-joint{stroke:var(--foreground)}
  #gt-double-ball-macpherson-v3 .gt-mount{stroke:var(--muted-foreground)}
  #gt-double-ball-macpherson-v3 .gt-marker{fill:var(--primary);stroke:var(--primary-foreground);stroke-width:2}
  #gt-double-ball-macpherson-v3 .gt-marker-text{fill:var(--primary-foreground);font-weight:500;text-anchor:middle;dominant-baseline:central}
  #gt-double-ball-macpherson-v3 .gt-svg-label{fill:var(--muted-foreground);font-weight:500}
  #gt-double-ball-macpherson-v3 .gt-legend{display:grid;gap:var(--space-2,8px);margin:0;padding:0;list-style:none}
  #gt-double-ball-macpherson-v3 .gt-legend li{display:grid;grid-template-columns:12px 20px 1fr;gap:var(--space-2,8px);align-items:baseline}
  #gt-double-ball-macpherson-v3 .gt-legend b{font-weight:500}
  #gt-double-ball-macpherson-v3 .gt-copy,
  #gt-double-ball-macpherson-v3 .gt-legend li>span:last-child{min-width:0}
  #gt-double-ball-macpherson-v3 .gt-legend li>span:last-child{overflow-wrap:break-word}
  #gt-double-ball-macpherson-v3 .gt-diagram{shape-rendering:geometricPrecision}
  #gt-double-ball-macpherson-v3 .gt-diagram path,
  #gt-double-ball-macpherson-v3 .gt-diagram line,
  #gt-double-ball-macpherson-v3 .gt-diagram polyline{stroke-linecap:round;stroke-linejoin:round}
  #gt-double-ball-macpherson-v3 .gt-swatch{inline-size:12px;block-size:12px;border-radius:50%}
  #gt-double-ball-macpherson-v3 .k-mount{background:var(--viz-series-6)}
  #gt-double-ball-macpherson-v3 .k-strut{background:var(--viz-series-5)}
  #gt-double-ball-macpherson-v3 .k-spring{background:var(--viz-series-2)}
  #gt-double-ball-macpherson-v3 .k-lateral{background:var(--viz-series-1)}
  #gt-double-ball-macpherson-v3 .k-tension{background:var(--viz-series-3)}
  #gt-double-ball-macpherson-v3 .k-knuckle{background:var(--foreground)}
  #gt-double-ball-macpherson-v3 .k-stabilizer{background:var(--destructive)}
  #gt-double-ball-macpherson-v3 .k-link{background:var(--viz-series-4)}
  #gt-double-ball-macpherson-v3 .k-wheel{background:var(--muted-foreground)}
  @media(max-width:600px){#gt-double-ball-macpherson-v3 .gt-layout{grid-template-columns:1fr}}
  @media (max-width: 719px) {
    #gt-double-ball-macpherson-v3 .gt-layout {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-3, 12px);
    }

    #gt-double-ball-macpherson-v3 .gt-copy {
      display: contents;
    }

    #gt-double-ball-macpherson-v3 .gt-copy > h3 { order: 1; }
    #gt-double-ball-macpherson-v3 .gt-copy > p { order: 2; }
    #gt-double-ball-macpherson-v3 .gt-diagram {
      order: 3;
      width: 100%;
      min-width: 0;
      max-height: none;
    }
    #gt-double-ball-macpherson-v3 .gt-copy > .gt-legend { order: 4; }
  }

/* --- front-double-wishbone-upper-lower-arm-v1 --- canonical card CSS, verbatim from accepted-suspension-cards/front-double-wishbone-upper-lower-arm-v1.html --- */
  #gt-accepted-front-double-wishbone-v1 .gt-card-stack {
    display: grid;
    gap: var(--space-4, 16px);
  }

  #gt-accepted-front-double-wishbone-v1 .gt-diagram {
    display: block;
    width: 100%;
    height: auto;
    color: var(--card-foreground);
  }

  #gt-accepted-front-double-wishbone-v1 .gt-wheel {
    fill: var(--muted-foreground);
    stroke: var(--foreground);
    stroke-width: 5;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-sidewall {
    fill: none;
    stroke: var(--border);
    stroke-width: 4;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-rim {
    fill: var(--card);
    stroke: var(--muted);
    stroke-width: 10;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-brake-disc {
    fill: var(--muted);
    stroke: var(--muted-foreground);
    stroke-width: 4;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-spoke {
    stroke: var(--muted-foreground);
    stroke-width: 17;
    stroke-linecap: round;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-caliper {
    fill: var(--viz-series-5);
    stroke: var(--card);
    stroke-width: 3;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-hub {
    fill: var(--card);
    stroke: var(--foreground);
    stroke-width: 6;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-chassis {
    stroke: var(--muted-foreground);
    stroke-width: 10;
    stroke-linecap: round;
    fill: none;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-upright {
    stroke: var(--foreground);
    stroke-width: 18;
    stroke-linecap: round;
    fill: none;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-arm {
    stroke: var(--viz-series-1);
    stroke-width: 13;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: color-mix(in srgb, var(--viz-series-1) 10%, transparent);
  }

  #gt-accepted-front-double-wishbone-v1 .gt-upper-arm {
    stroke: var(--viz-series-6);
    fill: color-mix(in srgb, var(--viz-series-6) 10%, transparent);
  }

  #gt-accepted-front-double-wishbone-v1 .gt-damper {
    stroke: var(--viz-series-2);
    stroke-width: 15;
    stroke-linecap: round;
    fill: none;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-spring {
    stroke: var(--viz-series-2);
    stroke-width: 5;
    fill: none;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-steering {
    stroke: var(--viz-series-3);
    stroke-width: 9;
    stroke-linecap: round;
    fill: none;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-stabilizer {
    stroke: var(--viz-series-4);
    stroke-width: 10;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-drop-link {
    stroke: var(--viz-series-5);
    stroke-width: 11;
    stroke-linecap: round;
    fill: none;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-drop-link-bracket {
    stroke: var(--viz-series-5);
    stroke-width: 9;
    stroke-linecap: round;
    fill: none;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-joint {
    fill: var(--card);
    stroke: var(--foreground);
    stroke-width: 4;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-mount {
    fill: var(--muted);
    stroke: var(--muted-foreground);
    stroke-width: 3;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-top-mount-plate {
    fill: var(--muted);
    stroke: var(--viz-series-6);
    stroke-width: 4;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-top-mount-bearing {
    fill: var(--card);
    stroke: var(--viz-series-6);
    stroke-width: 5;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-shock-mount-plate {
    fill: var(--muted);
    stroke: var(--muted-foreground);
    stroke-width: 4;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-shock-mount-bushing {
    fill: var(--card);
    stroke: var(--muted-foreground);
    stroke-width: 5;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-marker {
    fill: var(--primary);
    stroke: var(--primary-foreground);
    stroke-width: 2;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-marker-text {
    fill: var(--primary-foreground);
    font-weight: 500;
    text-anchor: middle;
    dominant-baseline: central;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-card-copy {
    display: grid;
    gap: var(--space-3, 12px);
    grid-column: 1;
    grid-row: 1;
    min-width: 0;
  }

  #gt-accepted-front-double-wishbone-v1 article {
    display: grid;
    grid-template-columns: minmax(240px, .8fr) minmax(0, 1.6fr);
    gap: var(--space-4, 16px);
    align-items: start;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-diagram {
    grid-column: 2;
    grid-row: 1;
    width: 100%;
    height: auto;
    shape-rendering: geometricPrecision;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-diagram path,
  #gt-accepted-front-double-wishbone-v1 .gt-diagram line,
  #gt-accepted-front-double-wishbone-v1 .gt-diagram polyline {
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-card-copy h3,
  #gt-accepted-front-double-wishbone-v1 .gt-card-copy p {
    margin: 0;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-legend {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-2, 8px);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-legend li {
    display: flex;
    gap: var(--space-2, 8px);
    align-items: baseline;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-legend li > span:last-child {
    min-width: 0;
    overflow-wrap: break-word;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-legend b {
    font-weight: 500;
  }

  #gt-accepted-front-double-wishbone-v1 .gt-swatch {
    inline-size: 12px;
    block-size: 12px;
    flex: 0 0 12px;
    border-radius: 50%;
    background: var(--muted-foreground);
  }

  #gt-accepted-front-double-wishbone-v1 .gt-key-mount { background: var(--viz-series-6); }
  #gt-accepted-front-double-wishbone-v1 .gt-key-shock-mount { background: var(--muted-foreground); }
  #gt-accepted-front-double-wishbone-v1 .gt-key-damper { background: var(--viz-series-2); }
  #gt-accepted-front-double-wishbone-v1 .gt-key-wheel { background: var(--muted-foreground); }
  #gt-accepted-front-double-wishbone-v1 .gt-key-upright { background: var(--foreground); }
  #gt-accepted-front-double-wishbone-v1 .gt-key-steering { background: var(--viz-series-3); }
  #gt-accepted-front-double-wishbone-v1 .gt-key-drop-link { background: var(--viz-series-5); }
  #gt-accepted-front-double-wishbone-v1 .gt-key-lower-arm { background: var(--viz-series-1); }
  #gt-accepted-front-double-wishbone-v1 .gt-key-upper-arm { background: var(--viz-series-6); }
  #gt-accepted-front-double-wishbone-v1 .gt-key-stabilizer { background: var(--viz-series-4); }

  @media (max-width: 560px) {
    #gt-accepted-front-double-wishbone-v1 article {
      grid-template-columns: 1fr;
    }

    #gt-accepted-front-double-wishbone-v1 .gt-card-copy,
    #gt-accepted-front-double-wishbone-v1 .gt-diagram {
      grid-column: 1;
      grid-row: auto;
    }

    #gt-accepted-front-double-wishbone-v1 .gt-legend {
      grid-template-columns: 1fr;
    }
  }
  @media (max-width: 719px) {
    #gt-accepted-front-double-wishbone-v1 article.card {
      display: grid;
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-3, 12px);
      align-items: start;
    }

    #gt-accepted-front-double-wishbone-v1 .gt-card-copy {
      display: contents;
    }

    #gt-accepted-front-double-wishbone-v1 .gt-card-copy > h3 { order: 1; }
    #gt-accepted-front-double-wishbone-v1 .gt-card-copy > p { order: 2; }
    #gt-accepted-front-double-wishbone-v1 .gt-diagram {
      order: 3;
      width: 100%;
      min-width: 0;
      max-height: none;
    }
    #gt-accepted-front-double-wishbone-v1 .gt-card-copy > .gt-legend { order: 4; }
  }

/* --- front-upper-wishbone-two-lower-links-v1 --- canonical card CSS, verbatim from accepted-suspension-cards/front-upper-wishbone-two-lower-links-v1.html --- */
  #gt-upper-wishbone-two-lower-v1 .gt-layout {
    display: grid;
    grid-template-columns: minmax(240px, .8fr) minmax(0, 1.6fr);
    gap: var(--space-4, 16px);
    align-items: start;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-copy {
    display: grid;
    gap: var(--space-3, 12px);
  }

  #gt-upper-wishbone-two-lower-v1 h3,
  #gt-upper-wishbone-two-lower-v1 p {
    margin: 0;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-count {
    color: var(--muted-foreground);
    font-weight: 500;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-legend {
    display: grid;
    gap: var(--space-2, 8px);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-legend li {
    display: grid;
    grid-template-columns: 12px 20px 1fr;
    gap: var(--space-2, 8px);
    align-items: baseline;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-legend b {
    font-weight: 500;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-copy,
  #gt-upper-wishbone-two-lower-v1 .gt-legend li > span:last-child {
    min-width: 0;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-legend li > span:last-child {
    overflow-wrap: break-word;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-diagram {
    shape-rendering: geometricPrecision;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-diagram path,
  #gt-upper-wishbone-two-lower-v1 .gt-diagram line,
  #gt-upper-wishbone-two-lower-v1 .gt-diagram polyline {
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-swatch {
    inline-size: 12px;
    block-size: 12px;
    border-radius: 50%;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-diagram {
    display: block;
    width: 100%;
    height: auto;
    color: var(--card-foreground);
  }

  #gt-upper-wishbone-two-lower-v1 .gt-label {
    fill: var(--muted-foreground);
    font-weight: 500;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-divider {
    stroke: var(--border);
    stroke-width: 2;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-body {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 10;
    stroke-linecap: round;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-subframe {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 16;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: .72;
    stroke-linejoin: round;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-wheel {
    fill: color-mix(in srgb, var(--muted-foreground) 30%, transparent);
    stroke: var(--foreground);
    stroke-width: 9;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-tire-sidewall {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 4;
    opacity: .5;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-rim {
    fill: var(--card);
    stroke: var(--muted-foreground);
    stroke-width: 8;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-disc {
    fill: var(--muted);
    stroke: var(--muted-foreground);
    stroke-width: 4;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-spoke {
    stroke: var(--muted-foreground);
    stroke-width: 12;
    stroke-linecap: round;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-knuckle {
    fill: color-mix(in srgb, var(--foreground) 13%, var(--card));
    stroke: var(--foreground);
    stroke-width: 9;
    stroke-linejoin: round;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-hub {
    fill: var(--card);
    stroke: var(--foreground);
    stroke-width: 7;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-upper {
    fill: none;
    stroke: var(--viz-series-6);
    stroke-width: 16;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-lower {
    fill: color-mix(in srgb, var(--viz-series-1) 18%, transparent);
    stroke: var(--viz-series-1);
    stroke-width: 10;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-tension {
    fill: color-mix(in srgb, var(--viz-series-3) 18%, transparent);
    stroke: var(--viz-series-3);
    stroke-width: 10;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-damper {
    fill: none;
    stroke: var(--viz-series-5);
    stroke-width: 23;
    stroke-linecap: round;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-damper-rod {
    fill: none;
    stroke: var(--viz-series-5);
    stroke-width: 9;
    stroke-linecap: round;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-spring {
    fill: none;
    stroke: var(--viz-series-2);
    stroke-width: 7;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-spring-seat {
    fill: none;
    stroke: var(--viz-series-2);
    stroke-width: 8;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-top-mount {
    fill: color-mix(in srgb, var(--viz-series-5) 20%, var(--card));
    stroke: var(--viz-series-5);
    stroke-width: 7;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-stabilizer {
    fill: none;
    stroke: var(--destructive);
    stroke-width: 11;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-drop-link {
    fill: none;
    stroke: var(--viz-series-4);
    stroke-width: 11;
    stroke-linecap: round;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-steering {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 8;
    stroke-linecap: round;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-joint,
  #gt-upper-wishbone-two-lower-v1 .gt-mount {
    fill: var(--card);
    stroke-width: 5;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-joint {
    stroke: var(--foreground);
  }

  #gt-upper-wishbone-two-lower-v1 .gt-mount {
    stroke: var(--muted-foreground);
  }

  #gt-upper-wishbone-two-lower-v1 .gt-hydro {
    fill: color-mix(in srgb, var(--viz-series-3) 28%, var(--card));
    stroke: var(--viz-series-3);
    stroke-width: 6;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-marker {
    fill: var(--primary);
    stroke: var(--primary-foreground);
    stroke-width: 2;
  }

  #gt-upper-wishbone-two-lower-v1 .gt-marker-text {
    fill: var(--primary-foreground);
    font-weight: 500;
    text-anchor: middle;
    dominant-baseline: central;
  }

  #gt-upper-wishbone-two-lower-v1 .k-upper { background: var(--viz-series-6); }
  #gt-upper-wishbone-two-lower-v1 .k-lower { background: var(--viz-series-1); }
  #gt-upper-wishbone-two-lower-v1 .k-tension { background: var(--viz-series-3); }
  #gt-upper-wishbone-two-lower-v1 .k-damper { background: var(--viz-series-5); }
  #gt-upper-wishbone-two-lower-v1 .k-spring { background: var(--viz-series-2); }
  #gt-upper-wishbone-two-lower-v1 .k-knuckle { background: var(--foreground); }
  #gt-upper-wishbone-two-lower-v1 .k-stabilizer { background: var(--destructive); }
  #gt-upper-wishbone-two-lower-v1 .k-link { background: var(--viz-series-4); }
  #gt-upper-wishbone-two-lower-v1 .k-wheel { background: var(--muted-foreground); }

  @media (max-width: 600px) {
    #gt-upper-wishbone-two-lower-v1 .gt-layout {
      grid-template-columns: 1fr;
    }
  }
  @media (max-width: 719px) {
    #gt-upper-wishbone-two-lower-v1 .gt-layout {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-3, 12px);
    }

    #gt-upper-wishbone-two-lower-v1 .gt-copy {
      display: contents;
    }

    #gt-upper-wishbone-two-lower-v1 .gt-copy > h3 { order: 1; }
    #gt-upper-wishbone-two-lower-v1 .gt-copy > p { order: 2; }
    #gt-upper-wishbone-two-lower-v1 .gt-diagram {
      order: 3;
      width: 100%;
      min-width: 0;
      max-height: none;
    }
    #gt-upper-wishbone-two-lower-v1 .gt-copy > .gt-legend { order: 4; }
  }

/* --- front-multilink-2upper-2lower-v1 --- canonical card CSS, verbatim from accepted-suspension-cards/front-multilink-2upper-2lower-v1.html --- */
  #gt-front-multilink-4arm-v1 .gt-layout{display:grid;grid-template-columns:minmax(240px,.8fr) minmax(0,1.6fr);gap:var(--space-4,16px);align-items:start}
  #gt-front-multilink-4arm-v1 .gt-copy{display:grid;gap:var(--space-3,12px)}
  #gt-front-multilink-4arm-v1 h3,#gt-front-multilink-4arm-v1 p{margin:0}
  #gt-front-multilink-4arm-v1 .gt-count{color:var(--muted-foreground);font-weight:500}
  #gt-front-multilink-4arm-v1 .gt-diagram{display:block;width:100%;height:auto;color:var(--card-foreground)}
  #gt-front-multilink-4arm-v1 .gt-separator{stroke:var(--border);stroke-width:2}
  #gt-front-multilink-4arm-v1 .gt-subframe{fill:none;stroke:var(--muted-foreground);stroke-width:16;stroke-linecap:round;stroke-linejoin:round;opacity:.72}
  #gt-front-multilink-4arm-v1 .gt-wheel{fill:none;stroke:var(--foreground);stroke-width:34}
  #gt-front-multilink-4arm-v1 .gt-wheel-inner{fill:none;stroke:var(--muted-foreground);stroke-width:4}
  #gt-front-multilink-4arm-v1 .gt-rim{fill:none;stroke:var(--muted-foreground);stroke-width:7}
  #gt-front-multilink-4arm-v1 .gt-spoke{fill:none;stroke:var(--muted-foreground);stroke-width:6;stroke-linecap:round}
  #gt-front-multilink-4arm-v1 .gt-knuckle{fill:color-mix(in srgb,var(--foreground) 13%,var(--card));stroke:var(--foreground);stroke-width:9;stroke-linejoin:round}
  #gt-front-multilink-4arm-v1 .gt-hub{fill:var(--card);stroke:var(--foreground);stroke-width:8}
  #gt-front-multilink-4arm-v1 .gt-upper-front{fill:none;stroke:var(--viz-series-1);stroke-width:15;stroke-linecap:round;stroke-linejoin:round}
  #gt-front-multilink-4arm-v1 .gt-upper-rear{fill:none;stroke:var(--viz-series-4);stroke-width:15;stroke-linecap:round;stroke-linejoin:round}
  #gt-front-multilink-4arm-v1 .gt-lower-front{fill:none;stroke:var(--viz-series-3);stroke-width:18;stroke-linecap:round;stroke-linejoin:round}
  #gt-front-multilink-4arm-v1 .gt-lower-rear{fill:none;stroke:var(--viz-series-6);stroke-width:20;stroke-linecap:round;stroke-linejoin:round}
  #gt-front-multilink-4arm-v1 .gt-damper{fill:none;stroke:var(--viz-series-5);stroke-width:26;stroke-linecap:round}
  #gt-front-multilink-4arm-v1 .gt-damper-rod{fill:none;stroke:var(--viz-series-5);stroke-width:9;stroke-linecap:round}
  #gt-front-multilink-4arm-v1 .gt-spring{fill:none;stroke:var(--viz-series-2);stroke-width:7}
  #gt-front-multilink-4arm-v1 .gt-spring-seat{fill:none;stroke:var(--viz-series-2);stroke-width:8}
  #gt-front-multilink-4arm-v1 .gt-top-mount{fill:color-mix(in srgb,var(--viz-series-5) 24%,var(--card));stroke:var(--viz-series-5);stroke-width:8}
  #gt-front-multilink-4arm-v1 .gt-stabilizer{fill:none;stroke:var(--destructive);stroke-width:12;stroke-linecap:round;stroke-linejoin:round}
  #gt-front-multilink-4arm-v1 .gt-stab-link{fill:none;stroke:var(--viz-series-7,var(--chart-5));stroke-width:12;stroke-linecap:round}
  #gt-front-multilink-4arm-v1 .gt-joint,#gt-front-multilink-4arm-v1 .gt-mount{fill:var(--card);stroke-width:5}
  #gt-front-multilink-4arm-v1 .gt-joint{stroke:var(--foreground)}
  #gt-front-multilink-4arm-v1 .gt-mount{stroke:var(--muted-foreground)}
  #gt-front-multilink-4arm-v1 .gt-marker{fill:var(--primary);stroke:var(--primary-foreground);stroke-width:2}
  #gt-front-multilink-4arm-v1 .gt-marker-text{fill:var(--primary-foreground);font-weight:500;text-anchor:middle;dominant-baseline:central}
  #gt-front-multilink-4arm-v1 .gt-svg-label{fill:var(--muted-foreground);font-weight:500}
  #gt-front-multilink-4arm-v1 .gt-legend{display:grid;gap:var(--space-2,8px);margin:0;padding:0;list-style:none}
  #gt-front-multilink-4arm-v1 .gt-legend li{display:grid;grid-template-columns:12px 24px 1fr;gap:var(--space-2,8px);align-items:baseline}
  #gt-front-multilink-4arm-v1 .gt-legend b{font-weight:500}
  #gt-front-multilink-4arm-v1 .gt-copy,
  #gt-front-multilink-4arm-v1 .gt-legend li>span:last-child{min-width:0}
  #gt-front-multilink-4arm-v1 .gt-legend li>span:last-child{overflow-wrap:break-word}
  #gt-front-multilink-4arm-v1 .gt-diagram{shape-rendering:geometricPrecision}
  #gt-front-multilink-4arm-v1 .gt-diagram path,
  #gt-front-multilink-4arm-v1 .gt-diagram line,
  #gt-front-multilink-4arm-v1 .gt-diagram polyline{stroke-linecap:round;stroke-linejoin:round}
  #gt-front-multilink-4arm-v1 .gt-swatch{inline-size:12px;block-size:12px;border-radius:50%}
  #gt-front-multilink-4arm-v1 .k-damper{background:var(--viz-series-5)}
  #gt-front-multilink-4arm-v1 .k-spring{background:var(--viz-series-2)}
  #gt-front-multilink-4arm-v1 .k-upper-front{background:var(--viz-series-1)}
  #gt-front-multilink-4arm-v1 .k-upper-rear{background:var(--viz-series-4)}
  #gt-front-multilink-4arm-v1 .k-lower-front{background:var(--viz-series-3)}
  #gt-front-multilink-4arm-v1 .k-lower-rear{background:var(--viz-series-6)}
  #gt-front-multilink-4arm-v1 .k-knuckle{background:var(--foreground)}
  #gt-front-multilink-4arm-v1 .k-stabilizer{background:var(--destructive)}
  #gt-front-multilink-4arm-v1 .k-link{background:var(--viz-series-7,var(--chart-5))}
  #gt-front-multilink-4arm-v1 .k-wheel{background:var(--muted-foreground)}
  @media(max-width:600px){#gt-front-multilink-4arm-v1 .gt-layout{grid-template-columns:1fr}}
  @media (max-width: 719px) {
    #gt-front-multilink-4arm-v1 .gt-layout {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-3, 12px);
    }

    #gt-front-multilink-4arm-v1 .gt-copy {
      display: contents;
    }

    #gt-front-multilink-4arm-v1 .gt-copy > h3 { order: 1; }
    #gt-front-multilink-4arm-v1 .gt-copy > p { order: 2; }
    #gt-front-multilink-4arm-v1 .gt-diagram {
      order: 3;
      width: 100%;
      min-width: 0;
      max-height: none;
    }
    #gt-front-multilink-4arm-v1 .gt-copy > .gt-legend { order: 4; }
  }

/* --- rear-torsion-beam-v1 --- canonical card CSS, verbatim from accepted-suspension-cards/rear-torsion-beam-v1.html --- */
  #gt-suspension-torsion-beam-v5 .gt-diagram {
    display: block;
    width: 100%;
    height: auto;
    color: var(--card-foreground);
  }

  #gt-suspension-torsion-beam-v5 .gt-body {
    stroke: var(--muted-foreground);
    stroke-width: 10;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
  }

  #gt-suspension-torsion-beam-v5 .gt-wheel {
    fill: var(--muted);
    stroke: var(--foreground);
    stroke-width: 8;
  }

  #gt-suspension-torsion-beam-v5 .gt-tire-groove {
    stroke: var(--muted-foreground);
    stroke-width: 4;
    stroke-linecap: round;
    fill: none;
  }

  #gt-suspension-torsion-beam-v5 .gt-rim {
    fill: var(--card);
    stroke: var(--muted-foreground);
    stroke-width: 5;
  }

  #gt-suspension-torsion-beam-v5 .gt-rim-spoke {
    stroke: var(--muted-foreground);
    stroke-width: 7;
    stroke-linecap: round;
  }

  #gt-suspension-torsion-beam-v5 .gt-hub {
    fill: var(--card);
    stroke: var(--foreground);
    stroke-width: 8;
  }

  #gt-suspension-torsion-beam-v5 .gt-beam {
    stroke: var(--viz-series-4);
    stroke-width: 30;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
  }

  #gt-suspension-torsion-beam-v5 .gt-spring-seat {
    stroke: var(--viz-series-2);
    stroke-width: 9;
    stroke-linecap: round;
  }

  #gt-suspension-torsion-beam-v5 .gt-spring {
    stroke: var(--viz-series-2);
    stroke-width: 7;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
  }

  #gt-suspension-torsion-beam-v5 .gt-damper-body {
    stroke: var(--viz-series-5);
    stroke-width: 18;
    stroke-linecap: round;
    fill: none;
  }

  #gt-suspension-torsion-beam-v5 .gt-damper-rod {
    stroke: var(--viz-series-5);
    stroke-width: 8;
    stroke-linecap: round;
    fill: none;
  }

  #gt-suspension-torsion-beam-v5 .gt-pivot {
    fill: var(--card);
    stroke: var(--viz-series-6);
    stroke-width: 11;
  }

  #gt-suspension-torsion-beam-v5 .gt-joint {
    fill: var(--card);
    stroke: var(--foreground);
    stroke-width: 4;
  }

  #gt-suspension-torsion-beam-v5 .gt-marker {
    fill: var(--primary);
    stroke: var(--primary-foreground);
    stroke-width: 2;
  }

  #gt-suspension-torsion-beam-v5 .gt-marker-text {
    fill: var(--primary-foreground);
    font-weight: 500;
    text-anchor: middle;
    dominant-baseline: central;
  }

  #gt-suspension-torsion-beam-v5 .gt-front {
    fill: var(--muted-foreground);
    text-anchor: start;
    font-weight: 500;
  }

  #gt-suspension-torsion-beam-v5 .gt-card-copy {
    display: grid;
    gap: var(--space-3, 12px);
    grid-column: 1;
    grid-row: 1;
    min-width: 0;
  }

  #gt-suspension-torsion-beam-v5 article {
    display: grid;
    grid-template-columns: minmax(240px, .8fr) minmax(0, 1.6fr);
    gap: var(--space-4, 16px);
    align-items: start;
  }

  #gt-suspension-torsion-beam-v5 .gt-diagram {
    grid-column: 2;
    grid-row: 1;
    width: 100%;
    height: auto;
    shape-rendering: geometricPrecision;
  }

  #gt-suspension-torsion-beam-v5 .gt-diagram path,
  #gt-suspension-torsion-beam-v5 .gt-diagram line,
  #gt-suspension-torsion-beam-v5 .gt-diagram polyline {
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-suspension-torsion-beam-v5 .gt-card-copy h3 {
    margin: 0;
  }

  #gt-suspension-torsion-beam-v5 .gt-legend {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-2, 8px);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  #gt-suspension-torsion-beam-v5 .gt-legend li {
    display: flex;
    gap: var(--space-2, 8px);
    align-items: baseline;
  }

  #gt-suspension-torsion-beam-v5 .gt-legend li > span:last-child {
    min-width: 0;
    overflow-wrap: break-word;
  }

  #gt-suspension-torsion-beam-v5 .gt-legend b {
    font-weight: 500;
  }

  #gt-suspension-torsion-beam-v5 .gt-swatch {
    inline-size: 12px;
    block-size: 12px;
    flex: 0 0 12px;
    border-radius: 50%;
  }

  #gt-suspension-torsion-beam-v5 .gt-key-damper { background: var(--viz-series-5); }
  #gt-suspension-torsion-beam-v5 .gt-key-spring { background: var(--viz-series-2); }
  #gt-suspension-torsion-beam-v5 .gt-key-pivot { background: var(--viz-series-6); }
  #gt-suspension-torsion-beam-v5 .gt-key-beam { background: var(--viz-series-4); }
  #gt-suspension-torsion-beam-v5 .gt-key-hub { background: var(--foreground); }
  #gt-suspension-torsion-beam-v5 .gt-key-wheel { background: var(--muted-foreground); }

  @media (max-width: 560px) {
    #gt-suspension-torsion-beam-v5 article {
      grid-template-columns: 1fr;
    }

    #gt-suspension-torsion-beam-v5 .gt-card-copy,
    #gt-suspension-torsion-beam-v5 .gt-diagram {
      grid-column: 1;
      grid-row: auto;
    }
  }
  @media (max-width: 719px) {
    #gt-suspension-torsion-beam-v5 article.card {
      display: grid;
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-3, 12px);
      align-items: start;
    }

    #gt-suspension-torsion-beam-v5 .gt-card-copy {
      display: contents;
    }

    #gt-suspension-torsion-beam-v5 .gt-card-copy > h3 { order: 1; }
    #gt-suspension-torsion-beam-v5 .gt-card-copy > p { order: 2; }
    #gt-suspension-torsion-beam-v5 .gt-diagram {
      order: 3;
      width: 100%;
      min-width: 0;
      max-height: none;
    }
    #gt-suspension-torsion-beam-v5 .gt-card-copy > .gt-legend { order: 4; }
  }

/* --- rear-torsion-beam-watt-link-v1 --- canonical card CSS, verbatim from accepted-suspension-cards/rear-torsion-beam-watt-link-v1.html --- */
  #gt-astra-j-watt-link-v2 .gt-layout {
    display: grid;
    grid-template-columns: minmax(240px, .8fr) minmax(0, 1.6fr);
    grid-template-areas: "copy diagram";
    gap: var(--space-4, 16px);
    align-items: start;
  }

  #gt-astra-j-watt-link-v2 .gt-diagram {
    grid-area: diagram;
    display: block;
    width: 100%;
    height: auto;
    color: var(--card-foreground);
  }

  #gt-astra-j-watt-link-v2 .gt-body {
    stroke: var(--muted-foreground);
    stroke-width: 10;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
  }

  #gt-astra-j-watt-link-v2 .gt-wheel {
    fill: var(--muted);
    stroke: var(--foreground);
    stroke-width: 8;
  }

  #gt-astra-j-watt-link-v2 .gt-tire-groove {
    stroke: var(--muted-foreground);
    stroke-width: 4;
    stroke-linecap: round;
    fill: none;
  }

  #gt-astra-j-watt-link-v2 .gt-rim {
    fill: var(--card);
    stroke: var(--muted-foreground);
    stroke-width: 5;
  }

  #gt-astra-j-watt-link-v2 .gt-rim-spoke {
    stroke: var(--muted-foreground);
    stroke-width: 7;
    stroke-linecap: round;
  }

  #gt-astra-j-watt-link-v2 .gt-hub {
    fill: var(--card);
    stroke: var(--foreground);
    stroke-width: 8;
  }

  #gt-astra-j-watt-link-v2 .gt-beam-arm {
    stroke: var(--viz-series-4);
    stroke-width: 30;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
  }

  #gt-astra-j-watt-link-v2 .gt-spring-seat {
    stroke: var(--viz-series-2);
    stroke-width: 9;
    stroke-linecap: round;
  }

  #gt-astra-j-watt-link-v2 .gt-spring {
    stroke: var(--viz-series-2);
    stroke-width: 7;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
  }

  #gt-astra-j-watt-link-v2 .gt-damper-body {
    stroke: var(--viz-series-5);
    stroke-width: 18;
    stroke-linecap: round;
    fill: none;
  }

  #gt-astra-j-watt-link-v2 .gt-damper-rod {
    stroke: var(--viz-series-5);
    stroke-width: 8;
    stroke-linecap: round;
    fill: none;
  }

  #gt-astra-j-watt-link-v2 .gt-pivot {
    fill: var(--card);
    stroke: var(--viz-series-6);
    stroke-width: 11;
  }

  #gt-astra-j-watt-link-v2 .gt-watt-rod {
    stroke: var(--viz-series-3);
    stroke-width: 13;
    stroke-linecap: round;
    fill: none;
  }

  #gt-astra-j-watt-link-v2 .gt-watt-rocker {
    stroke: var(--viz-series-6);
    stroke-width: 18;
    stroke-linecap: round;
    fill: none;
  }

  #gt-astra-j-watt-link-v2 .gt-crossmember {
    stroke: var(--muted-foreground);
    stroke-width: 18;
    stroke-linecap: round;
    fill: none;
  }

  #gt-astra-j-watt-link-v2 .gt-joint {
    fill: var(--card);
    stroke: var(--foreground);
    stroke-width: 4;
  }

  #gt-astra-j-watt-link-v2 .gt-marker {
    fill: var(--primary);
    stroke: var(--primary-foreground);
    stroke-width: 2;
  }

  #gt-astra-j-watt-link-v2 .gt-marker-text {
    fill: var(--primary-foreground);
    font-weight: 500;
    text-anchor: middle;
    dominant-baseline: central;
  }

  #gt-astra-j-watt-link-v2 .gt-front,
  #gt-astra-j-watt-link-v2 .gt-view-label {
    fill: var(--muted-foreground);
    font-weight: 500;
  }

  #gt-astra-j-watt-link-v2 .gt-view-label {
    text-anchor: middle;
  }

  #gt-astra-j-watt-link-v2 .gt-copy {
    grid-area: copy;
    display: grid;
    gap: var(--space-3, 12px);
  }

  #gt-astra-j-watt-link-v2 .gt-copy h3,
  #gt-astra-j-watt-link-v2 .gt-copy p {
    margin: 0;
  }

  #gt-astra-j-watt-link-v2 .gt-legend {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-2, 8px);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  #gt-astra-j-watt-link-v2 .gt-legend li {
    display: grid;
    grid-template-columns: 12px 20px 1fr;
    gap: var(--space-2, 8px);
    align-items: baseline;
  }

  #gt-astra-j-watt-link-v2 .gt-legend b {
    font-weight: 500;
  }

  #gt-astra-j-watt-link-v2 .gt-copy,
  #gt-astra-j-watt-link-v2 .gt-legend li > span:last-child {
    min-width: 0;
  }

  #gt-astra-j-watt-link-v2 .gt-legend li > span:last-child {
    overflow-wrap: break-word;
  }

  #gt-astra-j-watt-link-v2 .gt-diagram {
    shape-rendering: geometricPrecision;
  }

  #gt-astra-j-watt-link-v2 .gt-diagram path,
  #gt-astra-j-watt-link-v2 .gt-diagram line,
  #gt-astra-j-watt-link-v2 .gt-diagram polyline {
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-astra-j-watt-link-v2 .gt-swatch {
    inline-size: 12px;
    block-size: 12px;
    border-radius: 50%;
  }

  #gt-astra-j-watt-link-v2 .gt-key-damper { background: var(--viz-series-5); }
  #gt-astra-j-watt-link-v2 .gt-key-spring { background: var(--viz-series-2); }
  #gt-astra-j-watt-link-v2 .gt-key-pivot { background: var(--viz-series-6); }
  #gt-astra-j-watt-link-v2 .gt-key-beam-arm { background: var(--viz-series-4); }
  #gt-astra-j-watt-link-v2 .gt-key-watt { background: var(--viz-series-3); }
  #gt-astra-j-watt-link-v2 .gt-key-hub { background: var(--foreground); }
  #gt-astra-j-watt-link-v2 .gt-key-wheel { background: var(--muted-foreground); }

  @media (max-width: 600px) {
    #gt-astra-j-watt-link-v2 .gt-layout {
      grid-template-columns: 1fr;
      grid-template-areas:
        "copy"
        "diagram";
    }
  }
  @media (max-width: 719px) {
    #gt-astra-j-watt-link-v2 .gt-layout {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-3, 12px);
    }

    #gt-astra-j-watt-link-v2 .gt-copy {
      display: contents;
    }

    #gt-astra-j-watt-link-v2 .gt-copy > h3 { order: 1; }
    #gt-astra-j-watt-link-v2 .gt-copy > p { order: 2; }
    #gt-astra-j-watt-link-v2 .gt-diagram {
      order: 3;
      width: 100%;
      min-width: 0;
      max-height: none;
    }
    #gt-astra-j-watt-link-v2 .gt-copy > .gt-legend { order: 4; }
  }

/* --- rear-four-link-mqb-v1 --- canonical card CSS, verbatim from accepted-suspension-cards/rear-four-link-mqb-v1.html --- */
  /* Owner-corrected MQB geometry: preserve both projections and joints; show an open cradle instead of a filled box. */
  #gt-rear-four-link-mqb-v1 .gt-layout{display:grid;grid-template-columns:minmax(240px,.8fr) minmax(0,1.6fr);gap:var(--space-4,16px);align-items:start}
  #gt-rear-four-link-mqb-v1 .gt-copy{display:grid;gap:var(--space-3,12px)}
  #gt-rear-four-link-mqb-v1 h3,#gt-rear-four-link-mqb-v1 p{margin:0}
  #gt-rear-four-link-mqb-v1 .gt-count,#gt-rear-four-link-mqb-v1 .gt-label{color:var(--muted-foreground);font-weight:500}
  #gt-rear-four-link-mqb-v1 .gt-diagram{display:block;width:100%;height:auto;color:var(--card-foreground)}
  #gt-rear-four-link-mqb-v1 .gt-separator{stroke:var(--border);stroke-width:2}
  #gt-rear-four-link-mqb-v1 .gt-body{fill:none;stroke:var(--muted-foreground);stroke-width:10;stroke-linecap:round}
  #gt-rear-four-link-mqb-v1 .gt-subframe{fill:none;stroke:var(--muted-foreground);stroke-width:16;stroke-linecap:round;stroke-linejoin:round;opacity:.72}
  #gt-rear-four-link-mqb-v1 .gt-brace{fill:none;stroke:var(--muted-foreground);stroke-width:18;stroke-linecap:round}
  #gt-rear-four-link-mqb-v1 .gt-tire{fill:none;stroke:var(--foreground);stroke-width:34}
  #gt-rear-four-link-mqb-v1 .gt-sidewall{fill:none;stroke:var(--muted-foreground);stroke-width:4}
  #gt-rear-four-link-mqb-v1 .gt-rim{fill:none;stroke:var(--muted-foreground);stroke-width:7}
  #gt-rear-four-link-mqb-v1 .gt-spoke{fill:none;stroke:var(--muted-foreground);stroke-width:6;stroke-linecap:round}
  #gt-rear-four-link-mqb-v1 .gt-carrier{fill:color-mix(in srgb,var(--foreground) 14%,var(--card));stroke:var(--foreground);stroke-width:9;stroke-linejoin:round}
  #gt-rear-four-link-mqb-v1 .gt-hub{fill:var(--card);stroke:var(--foreground);stroke-width:8}
  #gt-rear-four-link-mqb-v1 .gt-upper{fill:none;stroke:var(--viz-series-6);stroke-width:17;stroke-linecap:round}
  #gt-rear-four-link-mqb-v1 .gt-trailing{fill:none;stroke:var(--viz-series-3);stroke-width:17;stroke-linecap:round}
  #gt-rear-four-link-mqb-v1 .gt-toe{fill:none;stroke:var(--viz-series-4);stroke-width:15;stroke-linecap:round}
  #gt-rear-four-link-mqb-v1 .gt-spring-arm{fill:color-mix(in srgb,var(--viz-series-1) 24%,transparent);stroke:var(--viz-series-1);stroke-width:9;stroke-linejoin:round}
  #gt-rear-four-link-mqb-v1 .gt-spring-seat{fill:none;stroke:var(--viz-series-2);stroke-width:7}
  #gt-rear-four-link-mqb-v1 .gt-spring{fill:none;stroke:var(--viz-series-2);stroke-width:8;stroke-linecap:round;stroke-linejoin:round}
  #gt-rear-four-link-mqb-v1 .gt-damper-body{fill:none;stroke:var(--viz-series-5);stroke-width:24;stroke-linecap:round}
  #gt-rear-four-link-mqb-v1 .gt-damper-rod{fill:none;stroke:var(--viz-series-5);stroke-width:10;stroke-linecap:round}
  #gt-rear-four-link-mqb-v1 .gt-stabilizer{fill:none;stroke:var(--destructive);stroke-width:12;stroke-linecap:round;stroke-linejoin:round}
  #gt-rear-four-link-mqb-v1 .gt-joint,#gt-rear-four-link-mqb-v1 .gt-mount{fill:var(--card);stroke-width:5}
  #gt-rear-four-link-mqb-v1 .gt-joint{stroke:var(--foreground)}
  #gt-rear-four-link-mqb-v1 .gt-mount{stroke:var(--muted-foreground)}
  #gt-rear-four-link-mqb-v1 .gt-marker{fill:var(--primary);stroke:var(--primary-foreground);stroke-width:2}
  #gt-rear-four-link-mqb-v1 .gt-marker-text{fill:var(--primary-foreground);font-weight:500;text-anchor:middle;dominant-baseline:central}
  #gt-rear-four-link-mqb-v1 .gt-svg-label{fill:var(--muted-foreground);font-weight:500}
  #gt-rear-four-link-mqb-v1 .gt-legend{display:grid;gap:var(--space-2,8px);margin:0;padding:0;list-style:none}
  #gt-rear-four-link-mqb-v1 .gt-legend li{display:grid;grid-template-columns:12px 20px 1fr;gap:var(--space-2,8px);align-items:baseline}
  #gt-rear-four-link-mqb-v1 .gt-legend b{font-weight:500}
  #gt-rear-four-link-mqb-v1 .gt-copy,
  #gt-rear-four-link-mqb-v1 .gt-legend li>span:last-child{min-width:0}
  #gt-rear-four-link-mqb-v1 .gt-legend li>span:last-child{overflow-wrap:break-word}
  #gt-rear-four-link-mqb-v1 .gt-diagram{shape-rendering:geometricPrecision}
  #gt-rear-four-link-mqb-v1 .gt-diagram path,
  #gt-rear-four-link-mqb-v1 .gt-diagram line,
  #gt-rear-four-link-mqb-v1 .gt-diagram polyline{stroke-linecap:round;stroke-linejoin:round}
  #gt-rear-four-link-mqb-v1 .gt-swatch{inline-size:12px;block-size:12px;border-radius:50%}
  #gt-rear-four-link-mqb-v1 .k-damper{background:var(--viz-series-5)}
  #gt-rear-four-link-mqb-v1 .k-spring{background:var(--viz-series-2)}
  #gt-rear-four-link-mqb-v1 .k-upper{background:var(--viz-series-6)}
  #gt-rear-four-link-mqb-v1 .k-trailing{background:var(--viz-series-3)}
  #gt-rear-four-link-mqb-v1 .k-toe{background:var(--viz-series-4)}
  #gt-rear-four-link-mqb-v1 .k-spring-arm{background:var(--viz-series-1)}
  #gt-rear-four-link-mqb-v1 .k-carrier{background:var(--foreground)}
  #gt-rear-four-link-mqb-v1 .k-stabilizer{background:var(--destructive)}
  #gt-rear-four-link-mqb-v1 .k-wheel{background:var(--muted-foreground)}
  @media(max-width:600px){#gt-rear-four-link-mqb-v1 .gt-layout{grid-template-columns:1fr}}
  @media (max-width: 719px) {
    #gt-rear-four-link-mqb-v1 .gt-layout {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-3, 12px);
    }

    #gt-rear-four-link-mqb-v1 .gt-copy {
      display: contents;
    }

    #gt-rear-four-link-mqb-v1 .gt-copy > h3 { order: 1; }
    #gt-rear-four-link-mqb-v1 .gt-copy > p { order: 2; }
    #gt-rear-four-link-mqb-v1 .gt-diagram {
      order: 3;
      width: 100%;
      min-width: 0;
      max-height: none;
    }
    #gt-rear-four-link-mqb-v1 .gt-copy > .gt-legend { order: 4; }
  }

/* --- rear-five-link-w124-v1 --- canonical card CSS, verbatim from accepted-suspension-cards/rear-five-link-w124-v1.html --- */
  /* Owner-corrected geometry: preserve all five links and joints; show an open cradle instead of a filled box. */
  #gt-rear-five-link-w124-v5 .gt-layout {
    display: grid;
    grid-template-columns: minmax(240px, .8fr) minmax(0, 1.6fr);
    grid-template-areas: "copy diagram";
    gap: var(--space-4, 16px);
    align-items: start;
  }

  #gt-rear-five-link-w124-v5 .gt-copy {
    grid-area: copy;
    display: grid;
    gap: var(--space-3, 12px);
  }

  #gt-rear-five-link-w124-v5 .gt-copy h3,
  #gt-rear-five-link-w124-v5 .gt-copy p {
    margin: 0;
  }

  #gt-rear-five-link-w124-v5 .gt-count,
  #gt-rear-five-link-w124-v5 .gt-projection-label {
    color: var(--muted-foreground);
    font-weight: 500;
  }

  #gt-rear-five-link-w124-v5 .gt-diagram {
    grid-area: diagram;
    display: block;
    width: 100%;
    height: auto;
    color: var(--card-foreground);
  }

  #gt-rear-five-link-w124-v5 .gt-separator {
    stroke: var(--border);
    stroke-width: 2;
  }

  #gt-rear-five-link-w124-v5 .gt-body {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 10;
    stroke-linecap: round;
  }

  #gt-rear-five-link-w124-v5 .gt-subframe {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 16;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: .72;
    stroke-linejoin: round;
  }

  #gt-rear-five-link-w124-v5 .gt-subframe-brace {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 18;
    stroke-linecap: round;
  }

  #gt-rear-five-link-w124-v5 .gt-tire {
    fill: none;
    stroke: var(--foreground);
    stroke-width: 34;
  }

  #gt-rear-five-link-w124-v5 .gt-sidewall {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 4;
  }

  #gt-rear-five-link-w124-v5 .gt-rim {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 7;
  }

  #gt-rear-five-link-w124-v5 .gt-spoke {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 6;
    stroke-linecap: round;
  }

  #gt-rear-five-link-w124-v5 .gt-carrier {
    fill: color-mix(in srgb, var(--foreground) 14%, var(--card));
    stroke: var(--foreground);
    stroke-width: 9;
    stroke-linejoin: round;
  }

  #gt-rear-five-link-w124-v5 .gt-carrier-detail {
    fill: color-mix(in srgb, var(--foreground) 10%, var(--card));
    stroke: var(--foreground);
    stroke-width: 8;
    stroke-linejoin: round;
  }

  #gt-rear-five-link-w124-v5 .gt-hub {
    fill: var(--card);
    stroke: var(--foreground);
    stroke-width: 8;
  }

  #gt-rear-five-link-w124-v5 .gt-camber-arm {
    fill: none;
    stroke: var(--viz-series-6);
    stroke-width: 16;
    stroke-linecap: round;
  }

  #gt-rear-five-link-w124-v5 .gt-longitudinal-rod {
    fill: none;
    stroke: var(--viz-series-3);
    stroke-width: 15;
    stroke-linecap: round;
  }

  #gt-rear-five-link-w124-v5 .gt-toe-rod {
    fill: none;
    stroke: var(--primary);
    stroke-width: 13;
    stroke-linecap: round;
  }

  #gt-rear-five-link-w124-v5 .gt-reaction-rod {
    fill: none;
    stroke: var(--viz-series-4);
    stroke-width: 17;
    stroke-linecap: round;
  }

  #gt-rear-five-link-w124-v5 .gt-spring-arm {
    fill: color-mix(in srgb, var(--viz-series-1) 24%, transparent);
    stroke: var(--viz-series-1);
    stroke-width: 9;
    stroke-linejoin: round;
  }

  #gt-rear-five-link-w124-v5 .gt-spring-seat {
    fill: none;
    stroke: var(--viz-series-2);
    stroke-width: 7;
  }

  #gt-rear-five-link-w124-v5 .gt-spring {
    fill: none;
    stroke: var(--viz-series-2);
    stroke-width: 8;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-rear-five-link-w124-v5 .gt-damper-body {
    fill: none;
    stroke: var(--viz-series-5);
    stroke-width: 24;
    stroke-linecap: round;
  }

  #gt-rear-five-link-w124-v5 .gt-damper-rod {
    fill: none;
    stroke: var(--viz-series-5);
    stroke-width: 10;
    stroke-linecap: round;
  }

  #gt-rear-five-link-w124-v5 .gt-stabilizer {
    fill: none;
    stroke: var(--destructive);
    stroke-width: 12;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-rear-five-link-w124-v5 .gt-joint,
  #gt-rear-five-link-w124-v5 .gt-mount {
    fill: var(--card);
    stroke-width: 5;
  }

  #gt-rear-five-link-w124-v5 .gt-joint { stroke: var(--foreground); }
  #gt-rear-five-link-w124-v5 .gt-mount { stroke: var(--muted-foreground); }

  #gt-rear-five-link-w124-v5 .gt-marker {
    fill: var(--primary);
    stroke: var(--primary-foreground);
    stroke-width: 2;
  }

  #gt-rear-five-link-w124-v5 .gt-marker-text {
    fill: var(--primary-foreground);
    font-weight: 500;
    text-anchor: middle;
    dominant-baseline: central;
  }

  #gt-rear-five-link-w124-v5 .gt-direction,
  #gt-rear-five-link-w124-v5 .gt-svg-label {
    fill: var(--muted-foreground);
    font-weight: 500;
  }

  #gt-rear-five-link-w124-v5 .gt-legend {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-2, 8px);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  #gt-rear-five-link-w124-v5 .gt-legend li {
    display: grid;
    grid-template-columns: 12px 20px 1fr;
    gap: var(--space-2, 8px);
    align-items: baseline;
  }

  #gt-rear-five-link-w124-v5 .gt-legend b { font-weight: 500; }

  #gt-rear-five-link-w124-v5 .gt-copy,
  #gt-rear-five-link-w124-v5 .gt-legend li > span:last-child {
    min-width: 0;
  }

  #gt-rear-five-link-w124-v5 .gt-legend li > span:last-child {
    overflow-wrap: break-word;
  }

  #gt-rear-five-link-w124-v5 .gt-diagram {
    shape-rendering: geometricPrecision;
  }

  #gt-rear-five-link-w124-v5 .gt-diagram path,
  #gt-rear-five-link-w124-v5 .gt-diagram line,
  #gt-rear-five-link-w124-v5 .gt-diagram polyline {
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-rear-five-link-w124-v5 .gt-swatch {
    inline-size: 12px;
    block-size: 12px;
    border-radius: 50%;
  }

  #gt-rear-five-link-w124-v5 .gt-key-damper { background: var(--viz-series-5); }
  #gt-rear-five-link-w124-v5 .gt-key-spring { background: var(--viz-series-2); }
  #gt-rear-five-link-w124-v5 .gt-key-camber { background: var(--viz-series-6); }
  #gt-rear-five-link-w124-v5 .gt-key-longitudinal { background: var(--viz-series-3); }
  #gt-rear-five-link-w124-v5 .gt-key-toe { background: var(--primary); }
  #gt-rear-five-link-w124-v5 .gt-key-reaction { background: var(--viz-series-4); }
  #gt-rear-five-link-w124-v5 .gt-key-spring-arm { background: var(--viz-series-1); }
  #gt-rear-five-link-w124-v5 .gt-key-carrier { background: var(--foreground); }
  #gt-rear-five-link-w124-v5 .gt-key-stabilizer { background: var(--destructive); }
  #gt-rear-five-link-w124-v5 .gt-key-wheel { background: var(--muted-foreground); }

  @media (max-width: 600px) {
    #gt-rear-five-link-w124-v5 .gt-layout {
      grid-template-columns: 1fr;
      grid-template-areas:
        "copy"
        "diagram";
    }
  }
  @media (max-width: 719px) {
    #gt-rear-five-link-w124-v5 .gt-layout {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-3, 12px);
    }

    #gt-rear-five-link-w124-v5 .gt-copy {
      display: contents;
    }

    #gt-rear-five-link-w124-v5 .gt-copy > h3 { order: 1; }
    #gt-rear-five-link-w124-v5 .gt-copy > p { order: 2; }
    #gt-rear-five-link-w124-v5 .gt-diagram {
      order: 3;
      width: 100%;
      min-width: 0;
      max-height: none;
    }
    #gt-rear-five-link-w124-v5 .gt-copy > .gt-legend { order: 4; }
  }

/* --- rear-integral-link-v1 --- canonical card CSS, verbatim from accepted-suspension-cards/rear-integral-link-v1.html --- */
  #gt-rear-integral-link-v1 .gt-layout {
    display: grid;
    grid-template-columns: minmax(250px, .84fr) minmax(0, 1.56fr);
    gap: var(--space-4, 16px);
    align-items: start;
  }

  #gt-rear-integral-link-v1 .gt-copy {
    display: grid;
    gap: var(--space-3, 12px);
    min-width: 0;
  }

  #gt-rear-integral-link-v1 h3,
  #gt-rear-integral-link-v1 p {
    margin: 0;
  }

  #gt-rear-integral-link-v1 .gt-count,
  #gt-rear-integral-link-v1 .gt-svg-label {
    color: var(--muted-foreground);
    font-weight: 500;
  }

  #gt-rear-integral-link-v1 .gt-diagram {
    display: block;
    width: 100%;
    height: auto;
    color: var(--card-foreground);
  }

  #gt-rear-integral-link-v1 .gt-separator {
    stroke: var(--border);
    stroke-width: 2;
  }

  #gt-rear-integral-link-v1 .gt-body {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 10;
    stroke-linecap: round;
  }

  #gt-rear-integral-link-v1 .gt-mount-bracket {
    fill: color-mix(in srgb, var(--muted) 70%, transparent);
    stroke: var(--muted-foreground);
    stroke-width: 6;
    stroke-linejoin: round;
  }

  #gt-rear-integral-link-v1 .gt-mount-bushing {
    fill: var(--card);
    stroke: var(--muted-foreground);
    stroke-width: 7;
  }

  #gt-rear-integral-link-v1 .gt-mount-label {
    fill: var(--muted-foreground);
    font-weight: 500;
    letter-spacing: .04em;
  }

  #gt-rear-integral-link-v1 .gt-tire {
    fill: none;
    stroke: var(--foreground);
    stroke-width: 34;
  }

  #gt-rear-integral-link-v1 .gt-sidewall {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 4;
  }

  #gt-rear-integral-link-v1 .gt-rim {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 7;
  }

  #gt-rear-integral-link-v1 .gt-spoke {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 6;
    stroke-linecap: round;
  }

  #gt-rear-integral-link-v1 .gt-carrier {
    fill: color-mix(in srgb, var(--foreground) 14%, var(--card));
    stroke: var(--foreground);
    stroke-width: 9;
    stroke-linejoin: round;
  }

  #gt-rear-integral-link-v1 .gt-hub {
    fill: var(--card);
    stroke: var(--foreground);
    stroke-width: 8;
  }

  #gt-rear-integral-link-v1 .gt-upper {
    fill: none;
    stroke: var(--viz-series-6);
    stroke-width: 17;
    stroke-linecap: round;
  }

  #gt-rear-integral-link-v1 .gt-toe {
    fill: none;
    stroke: var(--viz-series-4);
    stroke-width: 15;
    stroke-linecap: round;
  }

  #gt-rear-integral-link-v1 .gt-lower {
    fill: color-mix(in srgb, var(--viz-series-1) 24%, transparent);
    stroke: var(--viz-series-1);
    stroke-width: 9;
    stroke-linejoin: round;
  }

  #gt-rear-integral-link-v1 .gt-integral {
    fill: none;
    stroke: var(--viz-series-3);
    stroke-width: 24;
    stroke-linecap: round;
  }

  #gt-rear-integral-link-v1 .gt-integral-focus {
    fill: color-mix(in srgb, var(--viz-series-3) 18%, transparent);
    stroke: var(--viz-series-3);
    stroke-width: 4;
  }

  #gt-rear-integral-link-v1 .gt-spring-seat {
    fill: none;
    stroke: var(--viz-series-2);
    stroke-width: 7;
  }

  #gt-rear-integral-link-v1 .gt-spring {
    fill: none;
    stroke: var(--viz-series-2);
    stroke-width: 8;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-rear-integral-link-v1 .gt-damper-body {
    fill: none;
    stroke: var(--viz-series-5);
    stroke-width: 24;
    stroke-linecap: round;
  }

  #gt-rear-integral-link-v1 .gt-damper-rod {
    fill: none;
    stroke: var(--viz-series-5);
    stroke-width: 10;
    stroke-linecap: round;
  }

  #gt-rear-integral-link-v1 .gt-stabilizer-arm {
    fill: none;
    stroke: var(--destructive);
    stroke-width: 14;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-rear-integral-link-v1 .gt-stabilizer-section {
    fill: var(--card);
    stroke: var(--destructive);
    stroke-width: 9;
  }

  #gt-rear-integral-link-v1 .gt-stabilizer-core {
    fill: var(--destructive);
  }

  #gt-rear-integral-link-v1 .gt-drop-link {
    fill: none;
    stroke: var(--primary);
    stroke-width: 15;
    stroke-linecap: round;
  }

  #gt-rear-integral-link-v1 .gt-drop-link-joint {
    fill: var(--card);
    stroke: var(--primary);
    stroke-width: 6;
  }

  #gt-rear-integral-link-v1 .gt-joint,
  #gt-rear-integral-link-v1 .gt-mount {
    fill: var(--card);
    stroke-width: 5;
  }

  #gt-rear-integral-link-v1 .gt-joint {
    stroke: var(--foreground);
  }

  #gt-rear-integral-link-v1 .gt-mount {
    stroke: var(--muted-foreground);
  }

  #gt-rear-integral-link-v1 .gt-marker {
    fill: var(--primary);
    stroke: var(--primary-foreground);
    stroke-width: 2;
  }

  #gt-rear-integral-link-v1 .gt-marker-text {
    fill: var(--primary-foreground);
    font-weight: 500;
    text-anchor: middle;
    dominant-baseline: central;
  }

  #gt-rear-integral-link-v1 .gt-svg-label {
    fill: var(--muted-foreground);
  }

  #gt-rear-integral-link-v1 .gt-legend {
    display: grid;
    gap: var(--space-2, 8px);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  #gt-rear-integral-link-v1 .gt-legend li {
    display: grid;
    grid-template-columns: 12px 20px 1fr;
    gap: var(--space-2, 8px);
    align-items: baseline;
  }

  #gt-rear-integral-link-v1 .gt-legend b {
    font-weight: 500;
  }

  #gt-rear-integral-link-v1 .gt-legend li > span:last-child {
    min-width: 0;
    overflow-wrap: break-word;
  }

  #gt-rear-integral-link-v1 .gt-diagram {
    shape-rendering: geometricPrecision;
  }

  #gt-rear-integral-link-v1 .gt-diagram path,
  #gt-rear-integral-link-v1 .gt-diagram line,
  #gt-rear-integral-link-v1 .gt-diagram polyline {
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-rear-integral-link-v1 .gt-swatch {
    inline-size: 12px;
    block-size: 12px;
    border-radius: 50%;
  }

  #gt-rear-integral-link-v1 .k-damper { background: var(--viz-series-5); }
  #gt-rear-integral-link-v1 .k-spring { background: var(--viz-series-2); }
  #gt-rear-integral-link-v1 .k-upper { background: var(--viz-series-6); }
  #gt-rear-integral-link-v1 .k-toe { background: var(--viz-series-4); }
  #gt-rear-integral-link-v1 .k-lower { background: var(--viz-series-1); }
  #gt-rear-integral-link-v1 .k-integral { background: var(--viz-series-3); }
  #gt-rear-integral-link-v1 .k-carrier { background: var(--foreground); }
  #gt-rear-integral-link-v1 .k-stabilizer { background: var(--destructive); }
  #gt-rear-integral-link-v1 .k-drop-link { background: var(--primary); }
  #gt-rear-integral-link-v1 .k-wheel { background: var(--muted-foreground); }

  @media (max-width: 600px) {
    #gt-rear-integral-link-v1 .gt-layout {
      grid-template-columns: 1fr;
    }
  }
  @media (max-width: 719px) {
    #gt-rear-integral-link-v1 .gt-layout {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-3, 12px);
    }

    #gt-rear-integral-link-v1 .gt-copy {
      display: contents;
    }

    #gt-rear-integral-link-v1 .gt-copy > h3 { order: 1; }
    #gt-rear-integral-link-v1 .gt-copy > p { order: 2; }
    #gt-rear-integral-link-v1 .gt-diagram {
      order: 3;
      width: 100%;
      min-width: 0;
      max-height: none;
    }
    #gt-rear-integral-link-v1 .gt-copy > .gt-legend { order: 4; }
  }

/* --- rear-rigid-axle-4link-panhard-v1 --- canonical card CSS, verbatim from accepted-suspension-cards/rear-rigid-axle-4link-panhard-v1.html --- */
  #gt-rigid-axle-panhard-v2 .gt-layout {
    display: grid;
    grid-template-columns: minmax(240px, .8fr) minmax(0, 1.6fr);
    grid-template-areas: "copy diagram";
    gap: var(--space-4, 16px);
    align-items: start;
  }

  #gt-rigid-axle-panhard-v2 .gt-diagram {
    grid-area: diagram;
    display: block;
    width: 100%;
    height: auto;
    color: var(--card-foreground);
  }

  #gt-rigid-axle-panhard-v2 .gt-copy {
    grid-area: copy;
    display: grid;
    gap: var(--space-3, 12px);
  }

  #gt-rigid-axle-panhard-v2 .gt-copy h3,
  #gt-rigid-axle-panhard-v2 .gt-copy p {
    margin: 0;
  }

  #gt-rigid-axle-panhard-v2 .gt-chassis {
    stroke: var(--muted-foreground);
    stroke-width: 10;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
  }

  #gt-rigid-axle-panhard-v2 .gt-wheel {
    fill: color-mix(in srgb, var(--muted) 16%, transparent);
    stroke: var(--foreground);
    stroke-width: 8;
  }

  #gt-rigid-axle-panhard-v2 .gt-sidewall {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 4;
  }

  #gt-rigid-axle-panhard-v2 .gt-rim {
    fill: color-mix(in srgb, var(--card) 34%, transparent);
    stroke: var(--muted-foreground);
    stroke-width: 5;
  }

  #gt-rigid-axle-panhard-v2 .gt-spoke {
    stroke: var(--muted-foreground);
    stroke-width: 7;
    stroke-linecap: round;
  }

  #gt-rigid-axle-panhard-v2 .gt-hub {
    fill: var(--card);
    stroke: var(--foreground);
    stroke-width: 7;
  }

  #gt-rigid-axle-panhard-v2 .gt-axle {
    stroke: var(--viz-series-4);
    stroke-width: 25;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
  }

  #gt-rigid-axle-panhard-v2 .gt-axle-case {
    fill: color-mix(in srgb, var(--viz-series-4) 14%, var(--card));
    stroke: var(--viz-series-4);
    stroke-width: 9;
  }

  #gt-rigid-axle-panhard-v2 .gt-upper-link {
    stroke: var(--viz-series-6);
    stroke-width: 13;
    stroke-linecap: round;
    fill: none;
  }

  #gt-rigid-axle-panhard-v2 .gt-lower-link {
    stroke: var(--viz-series-1);
    stroke-width: 16;
    stroke-linecap: round;
    fill: none;
  }

  #gt-rigid-axle-panhard-v2 .gt-panhard {
    stroke: var(--viz-series-3);
    stroke-width: 14;
    stroke-linecap: round;
    fill: none;
  }

  #gt-rigid-axle-panhard-v2 .gt-spring-seat {
    stroke: var(--viz-series-2);
    stroke-width: 9;
    stroke-linecap: round;
  }

  #gt-rigid-axle-panhard-v2 .gt-spring {
    stroke: var(--viz-series-2);
    stroke-width: 7;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
  }

  #gt-rigid-axle-panhard-v2 .gt-damper-body {
    stroke: var(--viz-series-5);
    stroke-width: 18;
    stroke-linecap: round;
    fill: none;
  }

  #gt-rigid-axle-panhard-v2 .gt-damper-rod {
    stroke: var(--viz-series-5);
    stroke-width: 8;
    stroke-linecap: round;
    fill: none;
  }

  #gt-rigid-axle-panhard-v2 .gt-joint {
    fill: var(--card);
    stroke: var(--foreground);
    stroke-width: 4;
  }

  #gt-rigid-axle-panhard-v2 .gt-mount {
    fill: var(--card);
    stroke: var(--muted-foreground);
    stroke-width: 6;
  }

  #gt-rigid-axle-panhard-v2 .gt-marker {
    fill: var(--primary);
    stroke: var(--primary-foreground);
    stroke-width: 2;
  }

  #gt-rigid-axle-panhard-v2 .gt-marker-text {
    fill: var(--primary-foreground);
    font-weight: 500;
    text-anchor: middle;
    dominant-baseline: central;
  }

  #gt-rigid-axle-panhard-v2 .gt-front,
  #gt-rigid-axle-panhard-v2 .gt-view-label {
    fill: var(--muted-foreground);
    font-weight: 500;
  }

  #gt-rigid-axle-panhard-v2 .gt-view-label {
    text-anchor: middle;
  }

  #gt-rigid-axle-panhard-v2 .gt-legend {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-2, 8px);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  #gt-rigid-axle-panhard-v2 .gt-legend li {
    display: grid;
    grid-template-columns: 12px 20px 1fr;
    gap: var(--space-2, 8px);
    align-items: baseline;
  }

  #gt-rigid-axle-panhard-v2 .gt-legend b {
    font-weight: 500;
  }

  #gt-rigid-axle-panhard-v2 .gt-copy,
  #gt-rigid-axle-panhard-v2 .gt-legend li > span:last-child {
    min-width: 0;
  }

  #gt-rigid-axle-panhard-v2 .gt-legend li > span:last-child {
    overflow-wrap: break-word;
  }

  #gt-rigid-axle-panhard-v2 .gt-diagram {
    shape-rendering: geometricPrecision;
  }

  #gt-rigid-axle-panhard-v2 .gt-diagram path,
  #gt-rigid-axle-panhard-v2 .gt-diagram line,
  #gt-rigid-axle-panhard-v2 .gt-diagram polyline {
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-rigid-axle-panhard-v2 .gt-swatch {
    inline-size: 12px;
    block-size: 12px;
    border-radius: 50%;
  }

  #gt-rigid-axle-panhard-v2 .gt-key-spring { background: var(--viz-series-2); }
  #gt-rigid-axle-panhard-v2 .gt-key-damper { background: var(--viz-series-5); }
  #gt-rigid-axle-panhard-v2 .gt-key-upper { background: var(--viz-series-6); }
  #gt-rigid-axle-panhard-v2 .gt-key-lower { background: var(--viz-series-1); }
  #gt-rigid-axle-panhard-v2 .gt-key-axle { background: var(--viz-series-4); }
  #gt-rigid-axle-panhard-v2 .gt-key-wheel { background: var(--muted-foreground); }
  #gt-rigid-axle-panhard-v2 .gt-key-panhard { background: var(--viz-series-3); }

  @media (max-width: 600px) {
    #gt-rigid-axle-panhard-v2 .gt-layout {
      grid-template-columns: 1fr;
      grid-template-areas:
        "copy"
        "diagram";
    }
  }
  @media (max-width: 719px) {
    #gt-rigid-axle-panhard-v2 .gt-layout {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-3, 12px);
    }

    #gt-rigid-axle-panhard-v2 .gt-copy {
      display: contents;
    }

    #gt-rigid-axle-panhard-v2 .gt-copy > h3 { order: 1; }
    #gt-rigid-axle-panhard-v2 .gt-copy > p { order: 2; }
    #gt-rigid-axle-panhard-v2 .gt-diagram {
      order: 3;
      width: 100%;
      min-width: 0;
      max-height: none;
    }
    #gt-rigid-axle-panhard-v2 .gt-copy > .gt-legend { order: 4; }
  }

/* --- rear-rigid-axle-leaf-spring-v1 --- canonical card CSS, verbatim from accepted-suspension-cards/rear-rigid-axle-leaf-spring-v1.html --- */
  #gt-rear-rigid-leaf-v1 .gt-layout {
    display: grid;
    grid-template-columns: minmax(240px, .8fr) minmax(0, 1.6fr);
    gap: var(--space-4, 16px);
    align-items: start;
  }

  #gt-rear-rigid-leaf-v1 .gt-copy {
    display: grid;
    gap: var(--space-3, 12px);
  }

  #gt-rear-rigid-leaf-v1 .gt-copy h3 {
    margin: 0;
  }

  #gt-rear-rigid-leaf-v1 .gt-legend {
    display: grid;
    gap: var(--space-2, 8px);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  #gt-rear-rigid-leaf-v1 .gt-legend li {
    display: grid;
    grid-template-columns: 12px 20px 1fr;
    gap: var(--space-2, 8px);
    align-items: baseline;
  }

  #gt-rear-rigid-leaf-v1 .gt-legend b {
    font-weight: 500;
  }

  #gt-rear-rigid-leaf-v1 .gt-copy,
  #gt-rear-rigid-leaf-v1 .gt-legend li > span:last-child {
    min-width: 0;
  }

  #gt-rear-rigid-leaf-v1 .gt-legend li > span:last-child {
    overflow-wrap: break-word;
  }

  #gt-rear-rigid-leaf-v1 .gt-diagram {
    shape-rendering: geometricPrecision;
  }

  #gt-rear-rigid-leaf-v1 .gt-diagram path,
  #gt-rear-rigid-leaf-v1 .gt-diagram line,
  #gt-rear-rigid-leaf-v1 .gt-diagram polyline {
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  #gt-rear-rigid-leaf-v1 .gt-swatch {
    inline-size: 12px;
    block-size: 12px;
    border-radius: 50%;
  }

  #gt-rear-rigid-leaf-v1 .gt-diagram {
    display: block;
    width: 100%;
    height: auto;
    color: var(--card-foreground);
  }

  #gt-rear-rigid-leaf-v1 .gt-frame {
    stroke: var(--muted-foreground);
    stroke-width: 10;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
  }

  #gt-rear-rigid-leaf-v1 .gt-wheel {
    fill: color-mix(in srgb, var(--muted) 16%, transparent);
    stroke: var(--foreground);
    stroke-width: 8;
  }

  #gt-rear-rigid-leaf-v1 .gt-sidewall {
    fill: none;
    stroke: var(--muted-foreground);
    stroke-width: 4;
  }

  #gt-rear-rigid-leaf-v1 .gt-rim {
    fill: color-mix(in srgb, var(--card) 28%, transparent);
    stroke: var(--muted-foreground);
    stroke-width: 5;
  }

  #gt-rear-rigid-leaf-v1 .gt-spoke {
    stroke: var(--muted-foreground);
    stroke-width: 7;
    stroke-linecap: round;
  }

  #gt-rear-rigid-leaf-v1 .gt-hub {
    fill: var(--card);
    stroke: var(--foreground);
    stroke-width: 7;
  }

  #gt-rear-rigid-leaf-v1 .gt-leaf {
    stroke: var(--viz-series-2);
    stroke-width: 11;
    stroke-linecap: round;
    fill: none;
  }

  #gt-rear-rigid-leaf-v1 .gt-eye {
    fill: var(--card);
    stroke: var(--viz-series-1);
    stroke-width: 8;
  }

  #gt-rear-rigid-leaf-v1 .gt-shackle {
    stroke: var(--viz-series-6);
    stroke-width: 13;
    stroke-linecap: round;
    fill: none;
  }

  #gt-rear-rigid-leaf-v1 .gt-axle {
    fill: color-mix(in srgb, var(--viz-series-4) 16%, var(--card));
    stroke: var(--viz-series-4);
    stroke-width: 10;
  }

  #gt-rear-rigid-leaf-v1 .gt-u-bolt {
    stroke: var(--viz-series-3);
    stroke-width: 9;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
  }

  #gt-rear-rigid-leaf-v1 .gt-spring-plate {
    stroke: var(--viz-series-3);
    stroke-width: 12;
    stroke-linecap: round;
  }

  #gt-rear-rigid-leaf-v1 .gt-damper-body {
    stroke: var(--viz-series-5);
    stroke-width: 22;
    stroke-linecap: round;
    fill: none;
  }

  #gt-rear-rigid-leaf-v1 .gt-damper-rod {
    stroke: var(--viz-series-5);
    stroke-width: 9;
    stroke-linecap: round;
    fill: none;
  }

  #gt-rear-rigid-leaf-v1 .gt-joint {
    fill: var(--card);
    stroke: var(--foreground);
    stroke-width: 4;
  }

  #gt-rear-rigid-leaf-v1 .gt-marker {
    fill: var(--primary);
    stroke: var(--primary-foreground);
    stroke-width: 2;
  }

  #gt-rear-rigid-leaf-v1 .gt-marker-text {
    fill: var(--primary-foreground);
    font-weight: 500;
    text-anchor: middle;
    dominant-baseline: central;
  }

  #gt-rear-rigid-leaf-v1 .gt-front {
    fill: var(--muted-foreground);
    font-weight: 500;
  }

  #gt-rear-rigid-leaf-v1 .gt-key-leaf { background: var(--viz-series-2); }
  #gt-rear-rigid-leaf-v1 .gt-key-eye { background: var(--viz-series-1); }
  #gt-rear-rigid-leaf-v1 .gt-key-shackle { background: var(--viz-series-6); }
  #gt-rear-rigid-leaf-v1 .gt-key-clamp { background: var(--viz-series-3); }
  #gt-rear-rigid-leaf-v1 .gt-key-axle { background: var(--viz-series-4); }
  #gt-rear-rigid-leaf-v1 .gt-key-damper { background: var(--viz-series-5); }
  #gt-rear-rigid-leaf-v1 .gt-key-wheel { background: var(--muted-foreground); }

  @media (max-width: 600px) {
    #gt-rear-rigid-leaf-v1 .gt-layout {
      grid-template-columns: 1fr;
    }
  }
  @media (max-width: 719px) {
    #gt-rear-rigid-leaf-v1 .gt-layout {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-3, 12px);
    }

    #gt-rear-rigid-leaf-v1 .gt-copy {
      display: contents;
    }

    #gt-rear-rigid-leaf-v1 .gt-copy > h3 { order: 1; }
    #gt-rear-rigid-leaf-v1 .gt-copy > p { order: 2; }
    #gt-rear-rigid-leaf-v1 .gt-diagram {
      order: 3;
      width: 100%;
      min-width: 0;
      max-height: none;
    }
    #gt-rear-rigid-leaf-v1 .gt-copy > .gt-legend { order: 4; }
  }


/* ═══ S5 suspension selector — mobile full-screen diagram mode ══════════════
   Owner review 2026-07-25 (390x844 phone): on every one of the 12 cards the
   confirm action started below the fold (887-1339px vs an 844px viewport),
   the diagram got only 270px of a 390px screen, and the mechanic could read
   the preview as unfinished. The preview is therefore its own fixed
   full-screen layer showing exactly five things — back, one title, the
   complete diagram at full width, the "Обозначения" disclosure and the
   always-visible confirm action. Vehicle context, progress and the card's own
   duplicate heading are hidden behind/inside it.

   The !important flags below are deliberate and minimal: each canonical card
   styles its own layout through an ID-scoped selector (#gt-x .gt-layout),
   which outranks any class-only override. They re-flow the accepted card for
   one-hand phone reading; not one of them touches stroke, fill, geometry,
   numbering or label text. */

/* The mechanic shell's dark page background used to be a per-template inline
   <style> block. It is a shared visual rule, so it lives here now.
   NARROWED 2026-07-30: `.mech-app` is also reused, several DOM levels deep,
   by the draft editor's embedded read-only phone-mock preview (`.tw-ws-
   phone-screen.mech-app` in inspection_template_draft_edit.html) -- the
   original `body:has(.mech-app)` matched that page's body too, forcing the
   whole editor to this dark color regardless of its own theme toggle. On
   every real mechanic page `.mech-app` is base.html's own direct child of
   `<main>` (mechanic pages route through `{% block content %}` with an
   empty `{% block appheader %}`, so `.mech-app` IS that content, per
   base.html's own comment: "their content is wrapped in the separate,
   unrelated .theme-dark/.mech-app scope"); the editor's preview instance is
   nested many levels inside `<main>` (aside > pane-body > card > phone >
   phone-screen), never a direct child. `:has(main > .mech-app)` keeps the
   real mechanic shells dark and stops matching the embedded preview. */
body:has(main > .mech-app) { background: #14181E; }

/* Stage visibility must outrank the fixed-layer rules below. */
.mech-s5-stage.mech-s5-hidden { display: none !important; }

/* Freeze the document behind the full-screen diagram layer. */
html.mech-s5-preview-open, html.mech-s5-preview-open body { overflow: hidden; }

.mech-s5-preview {
  position: fixed; inset: 0; z-index: 60; display: flex; flex-direction: column;
  padding: calc(10px + env(safe-area-inset-top)) 12px calc(12px + env(safe-area-inset-bottom));
  background: linear-gradient(180deg, var(--mi-bg-2), var(--mi-bg));
  color: var(--mi-ink);
}
.mech-s5-preview-head { flex: none; display: flex; align-items: center; gap: 10px; }
.mech-s5-preview-head h2 {
  margin: 0; font-size: 17px; font-weight: 800; line-height: 1.25; letter-spacing: -.01em;
  min-width: 0; color: var(--mi-ink);
}
/* INSPECTION-STANDALONE-VISUAL-DELIVERY-CLOSURE-01-CORRECTION-01: 44px wide was under the 48px touch floor every
   other mechanic control meets; the workstation sheet raised only its height. */
.mech-s5-preview-back {
  flex: none; width: 48px; height: 48px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--mi-line-2); background: var(--mi-surface-3);
  color: var(--mi-ink-soft); font-size: 20px; line-height: 1; font-family: var(--mi-font);
}
.mech-s5-preview-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
  margin-top: 10px; display: flex; flex-direction: column;
}
/* Set by the selector only after it has measured that the card fits, so the
   diagram is centred in the free height instead of leaving a blank
   half-screen — and centring can never hide the top of an overflowing card. */
.mech-s5-preview-body.is-centered { justify-content: center; }
.mech-s5-preview .mech-s5-card-frame {
  margin-top: 0; padding: 10px; overflow-x: visible; background: var(--mi-surface);
}
.mech-s5-preview-cta { flex: none; margin-top: 12px; min-height: 56px; }

/* Re-flow the accepted card: complete diagram first, legend inside the
   disclosure. Layout only. */
.mech-s5-preview .mech-s5-card-frame article.card {
  display: block !important; margin: 0 !important; padding: 0 !important;
  border: 0 !important; background: none !important; box-shadow: none !important;
}
.mech-s5-preview .mech-s5-card-frame .gt-layout {
  display: block !important; gap: 0 !important; padding: 0 !important;
}
.mech-s5-preview .mech-s5-card-frame svg {
  display: block !important; width: 100% !important; height: auto !important;
  grid-column: auto !important; grid-row: auto !important;
  max-height: calc(100vh - 236px) !important;
  max-height: calc(100dvh - 236px) !important;
}
.mech-s5-preview .mech-s5-card-frame .gt-card-copy,
.mech-s5-preview .mech-s5-card-frame .gt-copy {
  display: grid !important; gap: 10px; margin: 0 !important; padding: 0 !important;
  grid-column: auto !important; grid-row: auto !important; min-width: 0;
}
/* One title per preview: the stage heading names the construction, so the
   card's own repeat of the same name is not shown again. */
.mech-s5-preview .mech-s5-card-frame .gt-card-copy > h3,
.mech-s5-preview .mech-s5-card-frame .gt-copy > h3 { display: none !important; }

.mech-s5-preview .mech-s5-legend { margin-top: 10px; border-top: 1px solid var(--mi-line); }
.mech-s5-preview .mech-s5-legend > summary {
  display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 10px 2px;
  cursor: pointer; list-style: none; font-size: 14.5px; font-weight: 700;
  color: var(--mi-ink-soft);
}
.mech-s5-preview .mech-s5-legend > summary::-webkit-details-marker { display: none; }
.mech-s5-preview .mech-s5-legend > summary::after {
  content: "\25BE"; margin-left: auto; font-size: 12px; color: var(--mi-ink-faint);
}
.mech-s5-preview .mech-s5-legend[open] > summary::after { content: "\25B4"; }
.mech-s5-preview .mech-s5-legend .gt-legend li { font-size: 13.5px; line-height: 1.4; }

/* PATH09-DIAGRAMS-PRODUCT-CONNECTION-01 — the Owner-accepted card drawings (`.gt-card-v2`, the partial generated by
   `python -m scripts.suspension_diagrams cards`): the drawing is a picture on its own light paper, loaded when its card
   opens, and «Обозначения» lists the drawing's numbers in the drawing's own frames — as on the phone previews the Owner
   accepted (scripts/suspension_diagrams/phone.py). */
.mech-s5-preview .mech-s5-card-frame img.gt-card-img {
  display: block !important; width: 100% !important; height: auto !important; background: #F7F7F4; border-radius: 6px;
  object-fit: contain; cursor: zoom-in;
  max-height: calc(100vh - 236px) !important;
  max-height: calc(100dvh - 236px) !important;
}
.mech-s5-preview.is-zoomed .mech-s5-card-frame img.gt-card-img { max-height: none !important; cursor: zoom-out; }
.gt-card-v2 .gt-legend { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.gt-card-v2 .gt-legend li { display: grid; grid-template-columns: 34px minmax(0, 1fr); gap: 10px; align-items: center;
  color: var(--mi-ink, #ECEFF3); }
.gt-card-v2 .gt-legend b { justify-self: start; min-width: 26px; height: 26px; padding: 0 3px; border-radius: 3px; display: grid;
  place-items: center; background: #fff; color: #1B1F23; font-weight: 800; font-size: 13px; box-shadow: inset 0 0 0 1.5px #1B1F23; }
.gt-card-v2 .gt-card-copy p { margin: 0; font-size: 13.5px; line-height: 1.45; color: var(--mi-ink-soft, #AEB7C2); }

/* Summary eyebrow — was an inline style= attribute on the template. */
.mech-s5-eyebrow { margin: 0 0 4px; font-size: 15px; color: var(--mi-ink-soft); }

/* ═══ PATH08-RECEPTION-OWNER-IMPLEMENTATION-01 — the inspection card as accepted (portions 6 and 7) ══════
   docs/kb/SOURCES/2026-09-19_owner_accepts_card_top.txt, …_accepts_card_results_and_photos.txt. ═══════ */

/* Under the car: phone, mechanic, mileage when recorded, «за N мин», and the created/taken/completed
   moments — one quiet line of labelled facts, not a second strip lower down. */
.rc-hero-facts { display: flex; flex-wrap: wrap; gap: 10px 32px; margin: 14px 0 0; }
.rc-hero-facts .rc-fact dt { margin-bottom: 2px; }
.rc-hero-facts .rc-fact dd { font-size: 0.92rem; }

/* «Итоги проверки» is two numbers (three when the mechanic said «не применимо»), with a ring while the
   work is under way. Zero remarks is grey, not red: nothing was found, and red would say otherwise. */
.rc-totals { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 28px; }
.rc-total { display: inline-flex; align-items: baseline; gap: 8px; font-size: 0.95rem; color: var(--gt-text-muted); }
.rc-total-num { font-size: 1.9rem; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; }
.rc-total-fault .rc-total-num { color: var(--gt-danger); }
.rc-total-fault.is-zero .rc-total-num { color: var(--gt-text-soft); }
.rc-total-ok .rc-total-num { color: var(--gt-success); }
.rc-total-na .rc-total-num { color: var(--gt-text); }
.rc-ring { flex: none; display: inline-flex; color: var(--gt-warning); }
.rc-ring.is-complete { color: var(--gt-success); }
/* The track must be visible or a third of a circle reads as a stray mark rather than as a third. */
.rc-ring-track { stroke: var(--gt-border); }
.rc-ring-fill { stroke: currentColor; }

/* Every photo of the inspection, once, under the name of its question; a fault's photo framed red. */
.rc-photos-summary { margin-top: 18px; }
.rc-photos-title { margin: 0 0 10px; font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--gt-text-muted); }
.rc-photos-strip { display: flex; flex-wrap: wrap; gap: 14px; }
.rc-photo-tile { margin: 0; width: 148px; }
.rc-photo-tile .rw-photo-link { display: block; padding: 0; border: 0; background: none; cursor: zoom-in; }
.rc-photo-thumb { display: block; width: 148px; height: 104px; object-fit: cover; border-radius: 10px; border: 2px solid var(--gt-photo-thumb-border); }
.rc-photo-tile.is-fault .rc-photo-thumb { border-color: var(--gt-danger); }
.rc-photo-tile figcaption { margin-top: 6px; font-size: 0.8rem; line-height: 1.3; color: var(--gt-text-muted); overflow-wrap: anywhere; }

/* Inside a system with remarks: the faults and every photographed item in view, the rest behind one
   quiet «Показать …» fold. */
.rw-more { margin-top: 6px; }
.rw-more-summary { cursor: pointer; list-style: none; padding: 8px 2px; font-size: 0.86rem; font-weight: 600; color: var(--gt-accent); }
.rw-more-summary::-webkit-details-marker { display: none; }
.rw-more[open] > .rw-more-summary { margin-bottom: 8px; }

/* ── the client report as accepted (portion 9) ─────────────────────────────────────────────────────────
   «Проверено без замечаний» is one line per system, in two columns — a system that found nothing does not
   need a card of its own, and two columns is what turns six pages into three. «Другие фото механика» keeps
   every photo that is not a fault's, under the name of the item it belongs to. */
.client-report-ok-lines { columns: 2; column-gap: 28px; margin: 0 0 18px; padding: 0; list-style: none; }
.client-report-ok-line { padding: 4px 0; font-size: 0.9rem; line-height: 1.45; break-inside: avoid; }
.client-report-ok-line b { font-weight: 600; }
/* «Другие фото механика» may flow across a page break between rows of photos (each figure stays whole); it used to be one
   unbreakable block of up to three quarters of a page, which left the page before it half empty. */
.client-report-other { break-inside: auto; }
.client-report-other-photos { display: flex; flex-wrap: wrap; gap: 14px; }
.client-report-other-photo { margin: 0; width: 210px; break-inside: avoid; }
/* PATH08-OB-REL-006-RECEPTION-CARD-REPORT-VISUAL-ACCEPTANCE-01-CORRECTION-01: this lane is held to the same whole-photo
   rule as `.client-report-photo` above. It had its own 210x150 box with `object-fit: cover` (the 174px floor made it
   210x174), so a 4:3 photo lost ~9% of its width and an upright phone photo ~38% of its height — on the page, in the
   preview and in the PDF, which embeds only what is painted. The box stays the accepted compact 210x174; the photo is
   fitted inside it whole and the space it does not fill is a neutral grey. The 4px padding keeps the photo inside the
   rounded corners, so the radius clips the frame and never the photo. */
.client-report-other-photo .client-report-photo { box-sizing: border-box; width: 210px; height: 174px; min-width: 0; min-height: 0; max-width: none; max-height: none; padding: 4px; object-fit: contain; object-position: center; background: #f1f3f5; border-radius: 8px; display: block; }
.client-report-other-photo figcaption { margin-top: 4px; font-size: 0.78rem; color: #56606c; }

/* ---------------------------------------------------------------------------
   PATH08-RECEPTION-OWNER-IMPLEMENTATION-02-MANAGEMENT-01 (2026-09-22) — «Управление» as the Owner accepted it
   (docs/kb/REPORTS/2026-09-19_PATH08-RECEPTION-OWNER-VISUAL-REVIEW-02-MANAGEMENT-ACCEPTED.md, pictures pU1b–pU10b).
   One token set for both themes (the colours the contrast count produced are the shared tokens already); nothing
   here touches a mechanic screen.
   --------------------------------------------------------------------------- */
.mgmt-home-card p strong { color: var(--gt-text); }
.mgmt-home-warn { margin-left: 12px; color: var(--gt-warning); font-weight: 600; }
.mgmt-home-grid { grid-template-columns: repeat(auto-fill, minmax(260px, 320px)); }

/* «Сотрудники»: filters in one row, applied at once */
.mgmt-filters { display: grid; grid-template-columns: minmax(320px, 1fr) 240px 240px; gap: 14px; }
.mgmt-filters-history { grid-template-columns: 280px 280px; }
.mgmt-filters .gt-field, .mgmt-filters .gt-select { min-width: 0; width: 100%; height: 44px; font-size: 15px; }
.mgmt-search { position: relative; display: block; margin: 0; }
.mgmt-search svg { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--gt-text-muted); pointer-events: none; }
.mgmt-search .gt-field { padding-left: 38px; }

.mgmt-staff { width: 100%; border-collapse: separate; border-spacing: 0 8px; }
.mgmt-staff th { text-align: left; font-size: 12px; letter-spacing: .07em; text-transform: uppercase; color: var(--gt-text-muted); padding: 0 18px 2px; font-weight: 700; }
.mgmt-staff td { background: var(--gt-surface); border-top: 1px solid var(--gt-border); border-bottom: 1px solid var(--gt-border); padding: 14px 18px; font-size: 15px; color: var(--gt-text); vertical-align: middle; }
.mgmt-staff td:first-child { border-left: 1px solid var(--gt-border); border-radius: 12px 0 0 12px; }
.mgmt-staff td:last-child { border-right: 1px solid var(--gt-border); border-radius: 0 12px 12px 0; text-align: right; white-space: nowrap; }
.mgmt-staff tr.is-off td { color: var(--gt-text-muted); }
.mgmt-staff-name strong { display: block; font-size: 16px; color: var(--gt-text); }
.mgmt-staff-name small { display: block; color: var(--gt-text-muted); font-size: 13.5px; margin-top: 2px; }
.mgmt-staff-actions { display: table-cell; }
.mgmt-staff-actions > * { vertical-align: middle; }
.mgmt-staff-actions .gt-btn + .mgmt-more { margin-left: 6px; }

.mgmt-chip { display: inline-flex; align-items: center; padding: 3px 10px; border-radius: 999px; font-size: 13px; font-weight: 700; margin: 2px 4px 2px 0; }
.mgmt-chip-ok { background: var(--gt-success-bg); color: var(--gt-success); }
.mgmt-chip-warn { background: var(--gt-warning-bg); color: var(--gt-warning); }
.mgmt-chip-off { background: var(--gt-surface-2); color: var(--gt-text-muted); }
.mgmt-chip-info { background: var(--gt-surface-2); color: var(--gt-accent); font-size: 12px; }
.mgmt-login { display: block; margin-top: 2px; font-size: 12.5px; color: var(--gt-text-muted); }

/* A receptionist's rights: switches with their real state */
.mgmt-switch-form { margin: 0; }
.mgmt-switch { display: flex; align-items: center; gap: 8px; margin: 3px 0; padding: 0; border: 0; background: none; color: var(--gt-text); font: inherit; font-size: 14px; cursor: pointer; text-align: left; }
.mgmt-switch.is-static { cursor: default; }
.mgmt-switch i { position: relative; flex: none; width: 34px; height: 20px; border-radius: 999px; background: var(--gt-field-border); }
.mgmt-switch i::after { content: ''; position: absolute; top: 3px; left: 3px; width: 14px; height: 14px; border-radius: 50%; background: #fff; transition: left .15s; }
.mgmt-switch.is-on i { background: var(--gt-solid-accent-bg); }
.mgmt-switch.is-on i::after { left: 17px; }
.mgmt-switch:focus-visible { outline: 2px solid var(--gt-accent); outline-offset: 2px; border-radius: 6px; }

/* The row menu «⋯» */
.mgmt-more { position: relative; display: inline-block; text-align: left; }
.mgmt-more > summary { list-style: none; cursor: pointer; }
.mgmt-more > summary::-webkit-details-marker { display: none; }
.mgmt-menu { position: absolute; right: 0; top: calc(100% + 6px); z-index: 20; min-width: 240px; padding: 6px; background: var(--gt-surface); border: 1px solid var(--gt-border); border-radius: 10px; box-shadow: 0 12px 30px rgba(0,0,0,.28); }
.mgmt-menu form { margin: 0; }
.mgmt-menu a, .mgmt-menu button { display: block; width: 100%; padding: 10px 12px; border: 0; border-radius: 7px; background: none; color: var(--gt-text); font: inherit; font-size: 14.5px; text-align: left; text-decoration: none; cursor: pointer; white-space: nowrap; }
.mgmt-menu a:hover, .mgmt-menu button:hover, .mgmt-menu a:focus-visible, .mgmt-menu button:focus-visible { background: var(--gt-surface-2); outline: none; }
.mgmt-menu .is-danger { color: var(--gt-danger); }
.mgmt-menu .is-quiet { color: var(--gt-text-muted); }
.mgmt-menu hr { border: 0; border-top: 1px solid var(--gt-border); margin: 4px 0; }

/* The login and password shown once */
.mgmt-credentials-overlay { display: flex; }
.mgmt-credentials { max-width: 520px; }
.mgmt-credentials-who { margin: 0 0 14px; color: var(--gt-text-muted); }
.mgmt-credentials-label { margin: 12px 0 6px; font-size: 14px; font-weight: 600; color: var(--gt-text-muted); }
.mgmt-credentials-note { margin: 14px 0 4px; color: var(--gt-text-muted); }
.mgmt-secret { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0; padding: 12px 14px; border-radius: 10px; background: var(--gt-surface-2); }
.mgmt-secret-value { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 22px; letter-spacing: .06em; user-select: all; overflow-wrap: anywhere; color: var(--gt-text); }
.mgmt-issue-form { display: flex; flex-direction: column; gap: 8px; }
.mgmt-issue-form .gt-modal-actions, .mgmt-credentials .gt-modal-actions, #gt-mfa-modal .gt-modal-actions { justify-content: flex-start; }
.mgmt-label { display: block; font-size: 14px; font-weight: 600; color: var(--gt-text-muted); margin: 0 0 6px; }

/* The staff form: two halves that fit 2560x1440 */
.mgmt-staff-form { display: grid; grid-template-columns: minmax(360px, 1fr); gap: 12px 40px; align-items: start; max-width: 1560px; }
.mgmt-staff-form.has-private { grid-template-columns: repeat(2, minmax(360px, 1fr)); }
.mgmt-form-half { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.mgmt-form-section { margin: 14px 0 6px; font-size: 12.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--gt-text-muted); font-weight: 700; }
.mgmt-form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 18px; }
.mgmt-form-cell { display: flex; flex-direction: column; min-width: 0; margin-bottom: 8px; }
.mgmt-form-cell .gt-field, .mgmt-form-half textarea.gt-field { width: 100%; height: 44px; font-size: 15px; box-sizing: border-box; }
.mgmt-form-half textarea.gt-field { height: auto; min-height: 44px; }
.mgmt-field-error { margin: 6px 0 0; color: var(--gt-danger); font-size: 14px; font-weight: 600; }
.gt-field.is-invalid, .mgmt-seg.is-invalid { outline: 2px solid var(--gt-danger); outline-offset: 0; }
.mgmt-check { display: flex; align-items: center; gap: 8px; margin-top: 8px; font-size: 14px; color: var(--gt-text); }
.mgmt-staff-form label.mgmt-check { justify-content: flex-start; width: auto; }
.mgmt-check input[type="checkbox"] { flex: none; width: 18px; height: 18px; margin: 0; accent-color: var(--gt-solid-accent-bg); }
.mgmt-seg { display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr); border: 1px solid var(--gt-border); border-radius: 10px; overflow: hidden; height: 44px; }
.mgmt-seg-option { position: relative; display: flex; }
.mgmt-seg-option input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.mgmt-seg-option span { flex: 1; display: flex; align-items: center; justify-content: center; font-size: 14.5px; line-height: 1.15; font-weight: 600; color: var(--gt-text); background: var(--gt-surface); padding: 0 8px; text-align: center; }
.mgmt-seg-option input:checked + span { background: var(--gt-surface-2); color: var(--gt-accent); box-shadow: inset 0 0 0 2px var(--gt-solid-accent-bg); }
.mgmt-seg-option input:focus-visible + span { outline: 2px solid var(--gt-accent); outline-offset: -3px; }
.mgmt-role-fixed { height: 44px; display: flex; align-items: center; padding: 0 12px; border: 1px solid var(--gt-border); border-radius: 10px; color: var(--gt-text); }
.mgmt-date-age { position: relative; }
.mgmt-age { position: absolute; right: 44px; top: 50%; transform: translateY(-50%); color: var(--gt-accent); font-weight: 700; font-size: 14px; pointer-events: none; }
.mgmt-removable { position: relative; }
.mgmt-remove { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); border: 0; background: none; color: var(--gt-text-muted); font-size: 20px; cursor: pointer; line-height: 1; padding: 4px 6px; }
.mgmt-add-phone { align-self: flex-start; border: 0; background: none; color: var(--gt-accent); font: inherit; font-size: 14px; font-weight: 600; cursor: pointer; padding: 2px 0 10px; }
.mgmt-form-actions { grid-column: 1 / -1; display: flex; gap: 10px; margin-top: 10px; }
.mgmt-form-actions .gt-btn { height: 44px; padding: 0 22px; font-size: 15px; }

/* «Устройства» */
.mgmt-devices { list-style: none; margin: 0; padding: 0; max-width: 820px; display: flex; flex-direction: column; gap: 8px; }
.mgmt-device { display: flex; align-items: center; gap: 14px; padding: 14px 16px; background: var(--gt-surface); border: 1px solid var(--gt-border); border-radius: 12px; }
.mgmt-device form { margin: 0 0 0 auto; }
.mgmt-device-icon { flex: none; width: 36px; height: 36px; border-radius: 9px; display: grid; place-items: center; background: var(--gt-surface-2); color: var(--gt-accent); }
.mgmt-device-text { display: flex; flex-direction: column; min-width: 0; }
.mgmt-device-text strong { color: var(--gt-text); }
.mgmt-device-text small { color: var(--gt-text-muted); font-size: 13.5px; margin-top: 2px; }

/* «Вход с кодом из приложения» */
.mgmt-mfa-card { max-width: 560px; padding: 20px 22px; margin-bottom: 14px; background: var(--gt-surface); border: 1px solid var(--gt-border); border-radius: 12px; }
.mgmt-mfa-card h2 { margin: 0; font-size: 18px; }
.mgmt-mfa-head { display: flex; align-items: center; gap: 14px; margin-bottom: 14px; }
.mgmt-mfa-icon { width: 40px; height: 40px; border-radius: 10px; display: grid; place-items: center; background: var(--gt-surface-2); color: var(--gt-text-muted); }
.mgmt-mfa-icon.is-on { background: var(--gt-success-bg); color: var(--gt-success); }
.mgmt-mfa-facts { display: grid; grid-template-columns: 180px 1fr; gap: 8px 16px; margin: 0 0 16px; }
.mgmt-mfa-facts dt { color: var(--gt-text-muted); }
.mgmt-mfa-facts dd { margin: 0; color: var(--gt-text); }
.mgmt-mfa-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; }
.mgmt-muted { color: var(--gt-text-muted); margin: 6px 0 10px; }
.mgmt-break { overflow-wrap: anywhere; font-size: 12.5px; }
.mgmt-code-field { font-size: 20px; letter-spacing: .15em; }
.mgmt-codes { columns: 2; font-size: 17px; }
.mgmt-inline-form { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
#gt-mfa-modal .gt-modal form { display: flex; flex-direction: column; gap: 6px; }

/* «История изменений» */
.mgmt-history { max-width: 1100px; }
.mgmt-day { margin: 18px 0 8px; font-size: 13px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--gt-text-muted); }
.mgmt-event { display: grid; grid-template-columns: 64px 1fr; gap: 16px; padding: 12px 18px; margin-bottom: 8px; background: var(--gt-surface); border: 1px solid var(--gt-border); border-radius: 10px; color: var(--gt-text); font-size: 15px; }
.mgmt-event time { color: var(--gt-text-muted); font-variant-numeric: tabular-nums; }
.mgmt-event small { display: block; margin-top: 3px; color: var(--gt-text-muted); font-size: 14px; }

/* The ONE refusal page */
.gt-refusal { min-height: 60vh; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; text-align: center; }
.gt-refusal-icon { width: 46px; height: 46px; border-radius: 12px; display: grid; place-items: center; background: var(--gt-surface-2); color: var(--gt-text-muted); }
.gt-refusal-title { margin: 0; font-size: 18px; font-weight: 700; color: var(--gt-text); }

/* The account window */
#gt-account-modal .gt-modal { max-width: 420px; padding: 18px; }
#gt-account-modal .gt-modal-title { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.gt-account-card { display: flex; flex-direction: column; }
.gt-account-card .gt-account-identity { display: flex; flex-direction: row; text-align: left; align-items: center; gap: 14px; padding: 6px 8px 14px; border-bottom: 1px solid var(--gt-border); }
.gt-account-initials { flex: none; width: 48px; height: 48px; border-radius: 50%; display: grid; place-items: center; background: var(--gt-surface-2); color: var(--gt-accent); font-weight: 800; font-size: 17px; }
.gt-account-who { display: flex; flex-direction: column; min-width: 0; }
.gt-account-name { font-size: 18px; font-weight: 700; color: var(--gt-text); overflow-wrap: anywhere; }
.gt-account-card .gt-account-role { color: var(--gt-text-muted); font-size: 14.5px; }
.gt-account-row { display: flex; align-items: center; gap: 12px; width: 100%; margin-top: 8px; padding: 12px 10px; border: 0; border-radius: 10px; background: none; color: var(--gt-text); font: inherit; font-size: 15.5px; text-align: left; text-decoration: none; cursor: pointer; }
.gt-account-row:hover, .gt-account-row:focus-visible { background: var(--gt-surface-2); outline: none; }
.gt-account-row-label { flex: 1; }
.gt-account-state { padding: 2px 10px; border-radius: 999px; font-size: 13px; font-weight: 700; background: var(--gt-surface-2); color: var(--gt-text-muted); }
.gt-account-state.is-on { background: var(--gt-success-bg); color: var(--gt-success); }
.gt-account-logout { margin: 0; border-top: 1px solid var(--gt-border); }

@media (max-width: 900px) {
  .mgmt-filters, .mgmt-filters-history { grid-template-columns: 1fr; }
  .mgmt-staff thead { display: none; }
  .mgmt-staff, .mgmt-staff tbody, .mgmt-staff tr, .mgmt-staff td { display: block; width: 100%; box-sizing: border-box; }
  .mgmt-staff tr { margin-bottom: 8px; border: 1px solid var(--gt-border); border-radius: 12px; background: var(--gt-surface); }
  .mgmt-staff td, .mgmt-staff td:first-child, .mgmt-staff td:last-child { border: 0; border-radius: 0; padding: 6px 14px; text-align: left; }
  .mgmt-staff-form.has-private, .mgmt-form-grid { grid-template-columns: 1fr; }
}

/* PATH08-RECEPTION-OWNER-IMPLEMENTATION-FIDELITY-03 — «Исправить» beside a client's name (board and card) and its window. */
/* The chosen client's chip holds one row now (name and «Изменить»); the row's 5px bottom margin, kept for a second line
   the chip no longer has, put both 2.5px above the chip's middle (measured). */
.rc-chosen-top:last-child { margin-bottom: 0; }
.rc-fix-trigger { flex: none; padding: 0; margin-left: 10px; border: 0; background: none; font: inherit; font-size: 0.85rem; font-weight: 600; color: var(--gt-accent); cursor: pointer; }
.rc-fix-trigger:hover, .rc-fix-trigger:focus-visible { text-decoration: none; color: var(--gt-accent-hover, var(--gt-accent)); } /* PATH09-OWNER-RECEPTION-ACCEPTANCE-CONSOLIDATED-CORRECTION-01: no underline */
.rc-fix-trigger:focus-visible { outline: 2px solid var(--gt-accent); outline-offset: 3px; border-radius: 4px; }
/* PATH09-OWNER-RECEPTION-ACCEPTANCE-CONSOLIDATED-CORRECTION-01: the client's ФИО note stands like the VIN note above it — its button under the sentence. */
.rc-name-note .rc-btn { margin-left: 28px; }
#rc-client-fix-modal .gt-modal { max-width: 460px; }
.rc-fix-form .rc-field { margin-bottom: 14px; }
.rc-fix-actions { display: flex; gap: 10px; margin-top: 6px; }
.rc-fix-actions .rc-btn { flex: 1; justify-content: center; }

/* ═══ PATH09-OWNER-RECEPTION-ACCEPTANCE-CONSOLIDATED-CORRECTION-01 — ONE CHOOSER LOOK FOR THE WHOLE INSPECTION MODULE ════════════════════════════════════════════════
   The Owner, 2026-10-06 (docs/kb/SOURCES/2026-10-06_owner_one_style_set_whole_inspection_module.txt): one style set
   for every page of the inspection module, receptionist's and owner's alike. His first finding was the open «Статус»
   list: the system's blue fill and square corners, not this product's style. Every single-choice <select> on a desk
   page (both desk themes: the board, the card, «Управление», «Шаблоны», «Безопасность», the sign-in) therefore opens
   the same list.

   * A NATIVE <select> STAYS a native <select>: keyboard, touch, forms and every tool that sets its value keep working.
     Where the browser can draw its list inside the page (`appearance: base-select`, Chrome 135+), the list takes the
     product's surface — a rounded 14px card, 44px rows, the quiet neutral hover, the chosen row in bold with a check.
     An older browser keeps its own list; nothing is hidden behind a script.
   * The closed control is not restyled here: every select already takes the field's look and the one chevron from
     the shared rules under «Forms», and a select with a look of its own (`.rc-select`, `.ro-status-select`, the
     editor's) keeps it. `:where()` holds the list rules at the weight of a bare `select`; only `appearance` carries
     real weight, so no class's own `appearance: none` can keep the system's list on some page.
   * `--gt-hover-quiet` is THE hover fill of every list row in the module: 8% of the theme's own text colour, so it
     reads the same in the light and the dark theme, never the accent tint the make list used to wear. */
:where(.theme-light, .theme-dark-desktop) { --gt-hover-quiet: var(--gt-surface-2); --gt-hover-quiet: color-mix(in srgb, var(--gt-text) 8%, transparent); }
@supports (appearance: base-select) {
  /* The one property that must win over every class's own `appearance: none`: the list a person opens is the same
     everywhere. Everything else here stays at the weight of a bare `select`. */
  :is(.theme-light, .theme-dark-desktop) select:not([multiple]):not([size]) { appearance: base-select; align-items: center; }
  /* Every single select already draws the module's one chevron (the shared caret rule under «Forms»), so the
     browser's own picker icon would be a second arrow beside it. */
  :where(.theme-light, .theme-dark-desktop) :where(select:not([multiple]):not([size]))::picker-icon { display: none; }
  :where(.theme-light, .theme-dark-desktop) :where(select:not([multiple]):not([size]))::picker(select) {
    appearance: base-select;
    margin-block: 6px; padding: 4px;
    border: 1px solid var(--gt-border); border-radius: 14px;
    background: var(--gt-surface); color: var(--gt-text);
    box-shadow: var(--gt-shadow-md);
  }
  :where(.theme-light, .theme-dark-desktop) :where(select:not([multiple]):not([size])) option {
    display: flex; align-items: center; gap: 10px; min-height: 44px; box-sizing: border-box;
    padding: 8px 12px; border-radius: 10px; color: var(--gt-text); font: inherit; cursor: pointer;
  }
  :where(.theme-light, .theme-dark-desktop) :where(select:not([multiple]):not([size])) option:checked { font-weight: 600; background: none; }
  :where(.theme-light, .theme-dark-desktop) :where(select:not([multiple]):not([size])) option:is(:hover, :focus-visible) { background: var(--gt-hover-quiet); outline: none; }
  :where(.theme-light, .theme-dark-desktop) :where(select:not([multiple]):not([size])) option::checkmark { order: 1; margin-left: auto; color: var(--gt-accent); }
  :where(.theme-light, .theme-dark-desktop) :where(select:not([multiple]):not([size])) option[value=""][disabled] { display: none; }
}
