/* ═══════════════════════════════════════════════════════════════════════════
   next-theme.css — the new design's SKIN for the LEGACY AngularJS screens
   ═══════════════════════════════════════════════════════════════════════════

   Companion to css/next-shell.css, but NOT tied to it. That file changes the
   app shell's GEOMETRY and is gated on `hsv-shell-next`; this one changes how
   the legacy screens LOOK — control borders, radii, focus, buttons, surfaces.

   THE GATE — `html.hsv-skin-next`, its own switch
   -----------------------------------------------
   Every rule is prefixed `html.hsv-skin-next`. Nothing here can match for a
   user who has not opted in, so their computed styles are byte-identical to
   before this file existed. That is not a nicety, it is the entire contract:
   the legacy app is still the product for everyone else.

   The class is NOT the shell's. It is applied by
   services/nextPreferenceService.js (applySkinClass, called from app.js's run
   block) whenever `hsv.skinNext` is set OR the shell is on — the shell implies
   the skin, because new chrome around 2012-styled forms is the exact mismatch
   this file exists to fix, but the reverse does not hold: a user can take the
   skin while staying on the legacy shell, which is the common case.

   It applies LIVE, unlike the shell. There is no React root to mount here and
   no markup that moves, so toggling the class is the whole operation and the
   settings screen can promise an immediate change instead of a refresh.

   ON <html>, NOT <body> — see the long note in directives/nextShell.js. The
   body's class attribute is Angular-interpolated
       class="body-bg full-screen theme-calcBackgroundColor-{{…}} …"
   and every theme digest rewrites the whole attribute, wiping anything added
   imperatively. <html> carries no Angular bindings at all.

   The leading `html` element selector is also doing specificity work. The
   legacy control borders come from a BODY THEME CLASS:

       .theme-bordersColor-black .ui-input input        -> (0,2,1)
       html.hsv-skin-next .ui-input input               -> (0,2,2)

   That extra element selector is what wins the fight, which is why almost
   nothing here needs `!important`. Where it does appear, it is never to win a
   specificity race — only because the thing being overridden cannot be beaten
   any other way. All six declarations, and their reasons:

       .ui2-filter-card border-color   vs css/ui-2026.css:41's own !important
       #treeControlWrapper button ×2   vs INLINE styles in treeControl.html
       #treeControlWrapper panel top   vs the same inline styles
       #treeControlWrapper panel top   vs entitiesManagement.css:94's !important
         (dueDates page)
       .type-customer height           vs INLINE style="height:31px" on four of
         its five views (programsCustomer, customers, documentTemplatesClients,
         loadCustomer) — same trap as the tree control above

   If you find yourself reaching for it anywhere else in this file, the
   selector is wrong.

   TWO TRAPS, BOTH FATAL, BOTH SILENT
   ----------------------------------
   1. NEVER use the `background` shorthand on an input. css/calculators.css
      paints the datepicker, currency and percent sprites with it:
          background: #ebebe4 url(/images/datepicker.png) no-repeat left 3px center;
      The DISABLED sprite rules are (0,2,0) and lose to the disabled block
      below at (0,3,2) — a `background:` there would reset background-image to
      none and the sprite would vanish from every disabled date field in the
      app. Longhands only: `background-color`, and `background-image` if you
      truly mean the image.

   2. NEVER set `display` on .btn. scss/common.scss:263 says
      `.btn { display: block }` and :267 `.btn.inline { display: inline-block }`.
      Hundreds of screens are laid out around that inversion of the Bootstrap
      default.

   HEIGHT — 31px -> 36px, and the third trap
   -----------------------------------------
   Controls are 36px here (legacy 31px, React ~41px). The input itself is the
   easy part. What breaks is everything sitting BESIDE it, because legacy
   aligns neighbours by hand rather than by layout:

     - Fixed-height siblings. The blue person button on a client field is
       `float: left; height: 31px`, so a 36px input beside a 31px button leaves
       a 5px gap along the bottom. There is no flex or table to save it. Every
       such neighbour is re-stated in the HEIGHT LOCKSTEP section below and
       must move with --hsv-n-ctl-h, not independently.

     - Hand-measured absolute offsets. A magnifier at `top: 6px` was centred
       for a 31px box; at 36px it needs 8.5px. The delta is +5px, so each one
       drifts +2.5px — visible, not subtle. Where the offset parent is the
       <label> (whose height equals the input's, because .ui-labelify is
       absolutely positioned and out of flow) these become
       `top: 50%; transform: translateY(-50%)` and stop being height-dependent
       for good.

       BUT NOT ALWAYS: css/entitiesManagement.css re-flows .ui-labelify to
       STATIC on two filter cards, which makes the label caption+input tall
       instead of input tall. Centring there puts the icon in the middle of
       the caption. Those stay measured. See the .ui-search block below — one
       selector, four different offsets, only one of which may be centred.

   Line-heights that are really heights: `.field-code` has no other vertical
   alignment, so its `line-height: 32px` was a 31px centring device. It tracks
   the control height (+1), via --hsv-n-code-lh.

   Not everything needs help. `.ui-button-input`'s button is itself in the
   controls.scss:449 height list; the datepicker/currency/chevron sprites use
   `background-position: … center`; .ui-labelify sits above the box; and
   `.custom-checkbox` rows have no wrapping label at all. Left alone on
   purpose — see the NOT COUPLED note at the end.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Values from web/src/styles/tokens.css. Written literally, not @imported:
   tokens.css lives inside the React bundle's stylesheet, which is injected
   lazily and only for users who opted in — this file has to work before it
   arrives. Same reasoning as the palette block in css/next-shell.css. */
html.hsv-skin-next {
    --hsv-n-page:      #fcfcfe;   /* --bg-page, the page behind the frames   */
    --hsv-n-surface:   #FFFFFF;   /* --bg-elevated, the frames themselves    */
    --hsv-n-bg:        #FFFFFF;   /* control fill                            */
    --hsv-n-fg:        #1A1A35;   /* --fg-1                                  */
    --hsv-n-fg-3:      #7A7A99;   /* --fg-3, placeholders                    */
    --hsv-n-fg-4:      #B0B0C6;   /* --fg-4, disabled text                   */
    --hsv-n-border:    #D0D3E2;   /* --border-strong                         */
    --hsv-n-sky:       #0096E1;   /* --brand-sky                             */
    --hsv-n-sky-d:     #007DBC;   /* --brand-sky hover                       */
    --hsv-n-navy:      #2D2D87;   /* --brand-navy                            */
    --hsv-n-danger:    #C0354E;   /* --danger                                */
    --hsv-n-danger-bg: #FBE4E8;   /* --danger-bg                             */
    --hsv-n-disabled:  #F8F9FD;   /* --bg-subtle                             */
    --hsv-n-tint-navy: rgba(45, 45, 135, .06);  /* --bg-tint-navy            */
    --hsv-n-tint-sky:  rgba(0, 150, 225, .08);  /* sky, same recipe as -tint-navy */
    --hsv-n-r-control: 6px;       /* --ext-radius-control                    */
    --hsv-n-r-btn:     8px;       /* --radius-md                             */
    --hsv-n-r-seg:     4px;       /* --radius-sm; SegmentedControl track/item */
    --hsv-n-ring:      0 0 0 3px rgba(0, 150, 225, .15);

    /* Added for the calc-map section navigator (below). --hsv-n-border above
       is already spoken for as the design's --border-STRONG (#D0D3E2), so the
       softer --border needs its own name here rather than reusing that one. */
    --hsv-n-fg-2:       #4A4A6B;  /* --fg-2, secondary text                  */
    --hsv-n-sunken:     #F4F5FB;  /* --bg-sunken, the nav panel ground       */
    --hsv-n-border-mid: #E4E6F0;  /* --border (NOT --border-strong)         */
    --hsv-n-border-sub: #EEF0F7;  /* --border-subtle, row hairline           */
    --hsv-n-r-card:     8px;      /* --radius-md, same number as -r-btn      */

    /* Control height. Legacy is 31px, React's own field is ~41px. Every height
       rule in this file references this, so moving it is one line — but the
       measured offsets in the .ui-search / .info-sign / .ui-client blocks are
       computed from a +5px delta and need re-deriving if it changes. */
    --hsv-n-ctl-h:     36px;
    /* .field-code centring: control height + 1. Legacy was 32px for 31px. */
    --hsv-n-code-lh:   37px;
}

/* ── Surfaces ─────────────────────────────────────────────────────────────
   The legacy calculator background is a body theme class driven by
   displayService.settings.calcBackgroundColor (blue=aliceblue, white=#FFFFFF,
   grey=#f9f9f9), defaulting to blue. Under the new design there is one
   arrangement, and it mirrors React's: a faintly tinted PAGE with WHITE cards
   on it. Legacy is the inverse (white body, tinted frames), so both halves
   have to be stated.

   .frame and .template-bg have NO base background rule anywhere — the theme
   class is their only source. That is why this block restates the whole
   selector list rather than just recolouring one variable.

   The picker is HIDDEN, not cleared — see the ng-if in app/views/settings.html.
   `dsettings` in localStorage keeps whatever the user chose, so turning the new
   design back off restores their old background exactly.

   Specificity: theme rules are (0,2,0), or (0,3,0) where they carry a :not().
   Prefixing with `html.hsv-skin-next body` adds one class and two elements,
   so every counterpart here is strictly higher. No !important, and no reliance
   on source order. Both tab-selector variants are listed because the -blue
   block (scss/themes.scss:5) omits the `.nav-tabs` segment that -grey/-white
   have; without both, a blue-theme user keeps aliceblue on the active tab. */
html.hsv-skin-next body.body-bg {
    background-color: var(--hsv-n-page);
}

html.hsv-skin-next body .template-bg,
html.hsv-skin-next body .frame,
html.hsv-skin-next body .frame-box,
html.hsv-skin-next body .modal-body:not(.bg-blue),
html.hsv-skin-next body .modal-footer:not(.bg-blue),
html.hsv-skin-next body .modal-left-addition:not(.bg-blue),
html.hsv-skin-next body .inner-calculator-content .calc-tabs.original-tabs .nav-tabs .active a.nav-link,
html.hsv-skin-next body .inner-calculator-content .calc-tabs.original-tabs .active a.nav-link,
html.hsv-skin-next body .modal-dialog .new-customer ul,
html.hsv-skin-next body .new-customer .frame-header select,
html.hsv-skin-next body .settings,
html.hsv-skin-next body .exchange-item.open {
    background-color: var(--hsv-n-surface);
}

/* The wizard breadcrumb chevrons are drawn as a border-colour triangle that
   has to match whatever surface sits behind them. Miss this and every
   breadcrumb on the import wizard grows an aliceblue arrowhead. */
html.hsv-skin-next body .wizard-bread-steps li::before {
    border-right-color: var(--hsv-n-surface);
}

/* ── Panel separation ─────────────────────────────────────────────────────
   REQUIRED by the surface change above, not decoration. Delete this block and
   the panels effectively disappear.

   Legacy told you where a panel ended purely by background contrast: an
   aliceblue `.frame` on a white body. `.frame` has no border and no shadow of
   its own anywhere in the legacy CSS. Now that the frame is white on a
   #FCFCFE page, that contrast is ~1%, and the boundary that groups a set of
   fields together is gone.

   React does not have this problem because its cards carry --shadow-1/2, and
   the design system says so explicitly: cards use SHADOW, not borders, and the
   shadows are navy-tinted rather than black. So this is the design-system
   answer to the surface change, not a workaround for it.

   --shadow-2, the card elevation. box-shadow only: it participates in
   painting, never in layout, so this stays inside the paint-only contract the
   rest of this phase keeps. */
html.hsv-skin-next body .frame,
html.hsv-skin-next body .frame-box {
    box-shadow: 0 4px 12px rgba(45, 45, 135, .08);
}

/* ── Inputs, selects, textareas ───────────────────────────────────────────
   The selector list is the union of scss/controls.scss:436-453 (geometry) and
   both theme-bordersColor-* lists in scss/themes.scss. It has to be
   reproduced verbatim: the legacy app does not use .form-control, so a bare
   <input> inside a wrapper class is the only thing that identifies a field.

   `.custom-checkbox input[type=number]` is in the geometry list but in
   NEITHER theme border list, so those inputs have no theme border today.
   Including it here is a small deliberate improvement, for opted-in users only.

   NOT touched, on purpose:
   - `padding` on selects. Legacy `padding: 5px 0 4px 0` leaves no horizontal
     padding because the native arrow is drawn inside the box; adding 12px a
     side clips it in narrow columns.
   - `font-size`. Moving .9em (14.4px) to 14px is a 0.4px shift that can change
     where a long Hebrew value ellipsises, for no visual gain. */
html.hsv-skin-next .ui-input input,
html.hsv-skin-next .ui-input-code input,
html.hsv-skin-next .ui-input-subcalc input,
html.hsv-skin-next .ui-input textarea,
html.hsv-skin-next .ui-textarea textarea,
html.hsv-skin-next .input-field input,
html.hsv-skin-next .ui-button-input input,
html.hsv-skin-next .ui-control .custom-checkbox input[type="text"],
html.hsv-skin-next .ui-control .custom-checkbox input[type="number"],
html.hsv-skin-next .ui-control .ui-radio input[type="text"],
html.hsv-skin-next .ui-select select,
html.hsv-skin-next .ui-select-subcalc select,
html.hsv-skin-next .ui-select-code select,
html.hsv-skin-next .input-field select,
html.hsv-skin-next .ui-control .custom-checkbox select {
    /* (0,2,2) vs the theme's (0,2,1); (0,4,2) vs (0,4,1) for .custom-checkbox */
    border: 1px solid var(--hsv-n-border);
    border-radius: var(--hsv-n-r-control);
    background-color: var(--hsv-n-bg);   /* LONGHAND — see trap 1 */
    color: var(--hsv-n-fg);
    transition: border-color .2s ease, box-shadow .2s ease;
}

/* ═══ HEIGHT LOCKSTEP ══════════════════════════════════════════════════════
   Everything from here to the end of this block is ONE change expressed in
   many places: the control box is --hsv-n-ctl-h, and so is every neighbour
   that has to line up with it. Change one without the others and you get the
   7px bottom-edge gap described in the header.

   `padding` and `line-height` are deliberately NOT touched. With
   box-sizing:border-box (Bootstrap's `*`), legacy's `padding: 5px 10px` and
   `line-height: 20px` still sit correctly inside a 36px box, and browsers
   vertically centre single-line input text against an explicit height
   regardless of line-height. Touching either would move text for no gain.  */

/* The fields themselves — scss/controls.scss:449 (inputs) and :584 (selects).
   Textareas are EXCLUDED: legacy gives them height:31px + max-height:200px and
   they auto-grow, so a fixed 36px would fight that. */
html.hsv-skin-next .ui-input input,
html.hsv-skin-next .ui-input-code input,
html.hsv-skin-next .ui-input-subcalc input,
html.hsv-skin-next .input-field input,
html.hsv-skin-next .ui-button-input input,
html.hsv-skin-next .ui-control .custom-checkbox input[type="text"],
html.hsv-skin-next .ui-control .custom-checkbox input[type="number"],
html.hsv-skin-next .ui-control .ui-radio input[type="text"],
html.hsv-skin-next .ui-select select,
html.hsv-skin-next .ui-select-subcalc select,
html.hsv-skin-next .ui-select-code select,
html.hsv-skin-next .input-field select,
html.hsv-skin-next .ui-control .custom-checkbox select {
    height: var(--hsv-n-ctl-h);
}

/* …and the same fields again with [disabled], because a DISABLED field is
   reached by higher-specificity rules than an enabled one and the rule above
   loses to them.
                                        .default-customer  = (0,2,1)
     css/main.css:487  .default-customer .ui-control input[disabled]  -> (0,3,1)
     the rule above    html.hsv-skin-next .ui-input input             -> (0,2,2)

   The attribute selector counts in the class column, so main.css wins and a
   disabled field stays at its legacy height while the button floated beside it
   moves — which is exactly the 6px step that showed up on the נישום field of
   the default-client bar, where the taxpayer input is permanently `disabled`.

   This is the same trap the disabled BORDER block further down already
   handles; height needed its own copy. Textareas stay out, as above. */
html.hsv-skin-next .ui-input input[disabled],
html.hsv-skin-next .ui-input-code input[disabled],
html.hsv-skin-next .ui-input-subcalc input[disabled],
html.hsv-skin-next .input-field input[disabled],
html.hsv-skin-next .ui-button-input input[disabled],
html.hsv-skin-next .ui-select select[disabled],
html.hsv-skin-next .ui-select-subcalc select[disabled],
html.hsv-skin-next .ui-select-code select[disabled],
html.hsv-skin-next .input-field select[disabled] {
    height: var(--hsv-n-ctl-h);
}

/* The floated person/refresh button on a client field — scss/controls.scss:40.
   `float: left` + a `width: calc(100% - 33px)` label, so nothing auto-aligns:
   this is THE rule behind the reported bug. Width stays 32px (the calc() is
   width-based and correct); only the height moves. */
html.hsv-skin-next .ui-control.ui-client button {
    height: var(--hsv-n-ctl-h);
}

/* The shared subcalc / document / radio / grid button group —
   scss/controls.scss:164, ~77 instances. Sits flush beside the field. */
html.hsv-skin-next .ui-control .ui-input-subcalc button,
html.hsv-skin-next .ui-control .ui-input-document button,
html.hsv-skin-next .ui-control .ui-select-document button,
html.hsv-skin-next .ui-control .ui-checkbox-document button,
html.hsv-skin-next .ui-control .ui-radio button,
html.hsv-skin-next .ui-control .ui-select-subcalc button,
html.hsv-skin-next .grid-container .ui-grid-document button {
    height: var(--hsv-n-ctl-h);
}

/* The `.ui-button` action slot — scss/controls.scss:106-132. Unlike every
   other in-control button, this one declares NO height: it is purely
   padding-derived (`padding: 4px 10px`), which left it at ~32px next to 36px
   fields, and css/depreciation.css:277 squeezes it further to `5px 7px`
   inside the depreciation modal.

   `min-height`, not `height`: these carry real labels ("פחת שנצבר", "מתואם")
   rather than a single icon, so they must stay free to grow. The padding is
   left alone — it is what gives them their horizontal size, and the modal's
   tighter override is deliberate. A <button> centres its own content, so the
   label ends up centred in the taller box with nothing further to do.

   These have no `.btn` class, which is why the `.btn` min-height rule further
   down does not reach them. */
html.hsv-skin-next .ui-control .ui-button button {
    min-height: var(--hsv-n-ctl-h);
}

/* `.field-code` — the `[23]` code label beside a field. `line-height` is its
   ONLY vertical alignment, so this is a height rule wearing a disguise.
   scss/controls.scss:186 and :504.

   `.ui-select-code .field-code` is listed explicitly even though legacy has NO
   such rule — it inherits :504's value today, so without it here the
   select-code rows would centre against 32px while input-code rows centre
   against 37px. */
html.hsv-skin-next .ui-control .ui-input-subcalc .field-code,
html.hsv-skin-next .ui-control .ui-select-subcalc .field-code,
html.hsv-skin-next .ui-input-code .field-code,
html.hsv-skin-next .ui-select-code .field-code {
    line-height: var(--hsv-n-code-lh);
}

/* angular ui-select — css/libs/select.min.css:322 and :331.
   BOTH, in one rule, on purpose: `.ui-select-match` carries `overflow:hidden`
   and is locked to `.form-control`'s height. Raise one and not the other and
   the match text clips with nothing on screen to suggest a CSS bug. */
html.hsv-skin-next .ui-select-container .form-control,
html.hsv-skin-next .ui-select-match {
    height: var(--hsv-n-ctl-h);
}

/* The two hand-rolled fake selects — css/confirmation-status-dropdown.css:179
   and :275. They share filter rows with real selects. */
html.hsv-skin-next .task-status-filter-btn,
html.hsv-skin-next .orka-multi-select-btn {
    height: var(--hsv-n-ctl-h);
}

/* Two more verbatim clones of the input geometry, each in its own file.
   css/grid-actions.css:76-84, css/store.css:335-345. `.type-customer` used to
   be a third clone here (css/entitiesManagement.css:24, a pill row beside
   real inputs — its `margin-top:24px` clearance is labelify-derived, not
   height-derived, so that stays untouched); it now gets its own rule below,
   because four of its five views hard-code `style="height:31px"` inline and
   need `!important` to be beaten at all — see the SEGMENTED CONTROL section. */
html.hsv-skin-next .grid-action-search input,
html.hsv-skin-next .store-page .small-input {
    height: var(--hsv-n-ctl-h);
}

/* `.btn-subcalc` — css/calculators.css:1755. The fix is `auto`, NOT a number.
   Its parent is already `display:flex; align-items:stretch` with
   `label{flex:1}` (:1745), so it WOULD track the input automatically — except
   `align-items:stretch` is ignored while the item has a definite cross size,
   and `height:31px` is definite. Removing the definite height hands the job to
   flex and this button never needs touching again, at any control height.

   The border-color is a PHASE-1 GAP being closed here: phase 1 never reached
   `.btn-subcalc`, so until now it has been showing `1px solid #000` glued to a
   #D0D3E2 field under the new design.

   `border-radius: 0` and `border-right: none` are NOT touched — the button is
   deliberately glued to the field. It survives this file's `.btn` radius rule
   only because `.ui-control .ui-input-with-subcalc .btn-subcalc` is (0,3,1)
   against that rule's (0,2,1); do not weaken either side. */
html.hsv-skin-next .ui-control .ui-input-with-subcalc .btn-subcalc {
    height: auto;
    border-color: var(--hsv-n-border);
}

/* …and the flex row has to actually BE input-height for that to work.
   Bootstrap 3 gives every <label> `margin-bottom: 5px`, which lands inside the
   flex container and makes it 5px taller than the field — so a stretched
   button overshoots the input's bottom edge by exactly that much. Caught by
   the bottom-edge assertion in e2e/specs/nextLegacyTheme.spec.ts, not by
   anything visible in the computed styles.

   scss/calculatorsCustom.scss:21-24 already fixes this, with the comment
   "cancel Bootstrap's label margin-bottom so the flex row stays input-height"
   — but only under `.ui-control.long-label`. This generalises it to every
   subcalc row, for opted-in users only. */
html.hsv-skin-next .ui-control .ui-input-with-subcalc label {
    margin-bottom: 0;
}

/* ── The יחיד/חברה segmented control ──────────────────────────────────────
   Transcribes web/src/ui/SegmentedControl.tsx's `filled` variant, the exact
   look React already uses for this same Person/Business choice
   (ClientPickerDialog.tsx:263-271). Legacy has no component for it — just two
   hand-rolled <button>s (.person-type-btn/.company-type-btn inside
   .type-customer) copy-pasted across five views: programsCustomer.html,
   dueDatesManagement.html, customers.html, documentTemplatesClients.html and
   loadCustomer.html — sharing one global rule at css/customers.css:260-279
   (1px grey border, square corners, #118dcf fill, 31px tall).

   TWO SELECTOR ARMS on every rule, bare and `.due-dates-filter-card`-qualified:
   that card already carries its own bespoke pill
   (css/entitiesManagement.css:22-49) at a higher specificity than a bare
   `.type-customer`/`.person-type-btn.active` rule would reach —
       .due-dates-filter-card .type-customer            (0,3,0)
       html.hsv-skin-next .type-customer                (0,2,1)  loses
       html.hsv-skin-next .due-dates-filter-card …       (0,3,1)  wins
   and the same gap exists one class deeper for `.active`. The qualified arm
   replaces that hand-made pill with this one; the bare arm covers every other
   view. `margin-top` on the dueDates copy is NOT touched — its 24px is
   labelify-derived (that card statics `.ui-labelify`), not height-derived. */
html.hsv-skin-next .type-customer,
html.hsv-skin-next .due-dates-filter-card .type-customer {
    /* height, not the shared HEIGHT LOCKSTEP rule above: four of these five
       views hard-code `style="height:31px"` inline, and nothing but
       !important beats an inline style — see the header inventory. */
    height: var(--hsv-n-ctl-h) !important;
    display: flex;               /* already true via customers.css; restated
                                     so this block does not depend on it */
    align-items: stretch;
    gap: 2px;
    padding: 2px;
    border: none;
    border-radius: var(--hsv-n-r-seg);
    background-color: var(--hsv-n-sunken);
}

html.hsv-skin-next .person-type-btn,
html.hsv-skin-next .company-type-btn,
html.hsv-skin-next .due-dates-filter-card .person-type-btn,
html.hsv-skin-next .due-dates-filter-card .company-type-btn {
    /* flex:1's flex-basis:0 supersedes customers.css's `width:50%` — no width
       declaration needed. border:none clears customers.css's 1px grey box and
       entitiesManagement.css's left/right hairline in one property. */
    flex: 1;
    border: none;
    border-radius: var(--hsv-n-r-seg);
    background-color: transparent;
    color: var(--hsv-n-fg-2);
    font-family: inherit;   /* buttons don't inherit reset.scss's Varela Round
                                app font; unset they render in the UA font */
    font-size: 14px;
    font-weight: 500;
    line-height: normal;
    transition: background-color .12s ease, color .12s ease;
}

html.hsv-skin-next .person-type-btn:hover,
html.hsv-skin-next .company-type-btn:hover,
html.hsv-skin-next .due-dates-filter-card .person-type-btn:hover,
html.hsv-skin-next .due-dates-filter-card .company-type-btn:hover {
    color: var(--hsv-n-navy);
}

html.hsv-skin-next .person-type-btn.active,
html.hsv-skin-next .company-type-btn.active,
html.hsv-skin-next .due-dates-filter-card .person-type-btn.active,
html.hsv-skin-next .due-dates-filter-card .company-type-btn.active {
    background-color: var(--hsv-n-sky);
    color: #FFFFFF;
}

/* .active:hover restated at its own higher specificity (three class-level
   selectors vs the bare :hover rule's two), rather than relying on this
   block being declared after it: today that source order already gives
   `.active` the win on the (0,2,0) tie, but that is fragile to reordering,
   and the same trap SegmentedControl.tsx and Tabs.tsx:165 both flag with
   `data-[state=on]:hover:…` deserves a rule that cannot regress by accident. */
html.hsv-skin-next .person-type-btn.active:hover,
html.hsv-skin-next .company-type-btn.active:hover,
html.hsv-skin-next .due-dates-filter-card .person-type-btn.active:hover,
html.hsv-skin-next .due-dates-filter-card .company-type-btn.active:hover {
    color: #FFFFFF;
}

/* loadCustomer.html can disable the person segment (ng-disabled +
   'is-disabled'); pointer-events are kept, matching Button's own disabled
   treatment, so a tooltip explaining why still attaches. */
html.hsv-skin-next .person-type-btn:disabled,
html.hsv-skin-next .company-type-btn:disabled,
html.hsv-skin-next .person-type-btn.is-disabled,
html.hsv-skin-next .company-type-btn.is-disabled {
    opacity: .4;
    cursor: not-allowed;
}

/* reset.scss:5 kills `outline` on every button app-wide at (0,2,2); without
   this there is no visible keyboard focus on this control at all. */
html.hsv-skin-next .person-type-btn:focus-visible,
html.hsv-skin-next .company-type-btn:focus-visible {
    outline: none;
    box-shadow: var(--hsv-n-ring);
}

/* Focus. :focus, not React's :focus-visible — a legacy text input is always
   focus-visible once you type in it, and :focus-visible on <select> is
   inconsistent across the Chromium versions this app still supports. */
html.hsv-skin-next .ui-input input:focus,
html.hsv-skin-next .ui-input-code input:focus,
html.hsv-skin-next .ui-input-subcalc input:focus,
html.hsv-skin-next .ui-input textarea:focus,
html.hsv-skin-next .ui-textarea textarea:focus,
html.hsv-skin-next .input-field input:focus,
html.hsv-skin-next .ui-select select:focus,
html.hsv-skin-next .ui-select-subcalc select:focus,
html.hsv-skin-next .ui-select-code select:focus,
html.hsv-skin-next .input-field select:focus {
    outline: none;
    border-color: var(--hsv-n-sky);
    box-shadow: var(--hsv-n-ring);
}

/* scss/controls.scss:558-561 `.ui-input.hover label:hover input` is (0,3,2)
   and would TIE the focus rule above when hovering an already-focused field.
   State it at (0,3,3) so the outcome does not depend on source order. */
html.hsv-skin-next .ui-input.hover label:hover input,
html.hsv-skin-next .ui-input-code.hover label:hover input {
    border-color: var(--hsv-n-border);
}

/* Placeholders. These DELIBERATELY lose to scss/controls.scss:493-496
   (`.ui-input input[required].ng-dirty::-webkit-input-placeholder`), which is
   (0,3,2) against this (0,2,3) — the class column decides, so the red
   required-and-dirty signal survives. That is the correct outcome; do not
   "fix" it by raising the specificity here.
   The two pseudo-elements cannot be comma-combined: an unknown selector in a
   list invalidates the whole rule in some engines. */
html.hsv-skin-next .ui-input input::-webkit-input-placeholder,
html.hsv-skin-next .ui-input textarea::-webkit-input-placeholder,
html.hsv-skin-next .input-field input::-webkit-input-placeholder {
    color: var(--hsv-n-fg-3);
}
html.hsv-skin-next .ui-input input::placeholder,
html.hsv-skin-next .ui-input textarea::placeholder,
html.hsv-skin-next .input-field input::placeholder {
    color: var(--hsv-n-fg-3);
}

/* Disabled — the specificity trap, and the easiest thing in this file to get
   wrong. The theme rules hit disabled controls at (0,3,1)
       .theme-bordersColor-black select[disabled]:not(.regular-bg)
   which is a whole class HIGHER than the enabled case. A gated rule at
   (0,2,2) does not beat it and a disabled select would keep its black border,
   so [disabled] has to be in the selector here.

   background-color ONLY, never the shorthand: this rule at (0,3,2) outranks
   the disabled sprite rules at (0,2,0), so `background:` here would delete
   /images/datepicker.png from every disabled date field. See trap 1. */
html.hsv-skin-next .ui-input input[disabled],
html.hsv-skin-next .ui-input-code input[disabled],
html.hsv-skin-next .ui-input-subcalc input[disabled],
html.hsv-skin-next .ui-input textarea[disabled],
html.hsv-skin-next .ui-textarea textarea[disabled],
html.hsv-skin-next .input-field input[disabled],
html.hsv-skin-next .ui-select select[disabled],
html.hsv-skin-next .ui-select-subcalc select[disabled],
html.hsv-skin-next .ui-select-code select[disabled],
html.hsv-skin-next .input-field select[disabled] {
    background-color: var(--hsv-n-disabled);
    border-color: var(--hsv-n-border);
    color: var(--hsv-n-fg);
}

html.hsv-skin-next button.lockable[disabled]:not(.regular-bg),
html.hsv-skin-next button.lockable[disabled]:active {
    /* (0,4,2) vs the theme's (0,3,1) */
    background-color: var(--hsv-n-disabled);
    border-color: var(--hsv-n-border);
    color: var(--hsv-n-fg-4);
}

/* ── angular ui-select ────────────────────────────────────────────────────
   css/libs/select.min.css:314-333 is the only place these are styled
   (`border:1px solid #000; height:31px`), and it is linked before this file,
   so we win on source order as well as specificity.

   .ui-select-match is height:31px + overflow:hidden and locked to
   .form-control's height — leave the height alone, or the match text clips.
   Only the corner needs to follow. */
html.hsv-skin-next .ui-select-container .form-control {
    border: 1px solid var(--hsv-n-border);
    border-radius: var(--hsv-n-r-control);
    background-color: var(--hsv-n-bg);
    color: var(--hsv-n-fg);
    box-shadow: none;                 /* kills Bootstrap 3's inset shadow */
}
html.hsv-skin-next .ui-select-container .form-control:focus,
html.hsv-skin-next .ui-select-container.open .form-control {
    border-color: var(--hsv-n-sky);
    box-shadow: var(--hsv-n-ring);
}
html.hsv-skin-next .ui-select-match {
    border-radius: var(--hsv-n-r-control);
}

/* Any bare Bootstrap-classed field the legacy app has outside a ui-select,
   and BS3's own #66afe9 focus glow. */
html.hsv-skin-next .form-control {
    border-radius: var(--hsv-n-r-control);
    border-color: var(--hsv-n-border);
    box-shadow: none;
}
html.hsv-skin-next .form-control:focus {
    border-color: var(--hsv-n-sky);
    box-shadow: var(--hsv-n-ring);
}

/* ── The two hand-rolled fake selects ─────────────────────────────────────
   css/confirmation-status-dropdown.css:175-195 and :272-293 — both
   `height:31px; border:1px solid #000; border-radius:0`. Height untouched.
   Both set `outline:none`, so both need an explicit :focus or a keyboard user
   gets nothing at all. .orka-multi-select-btn already declares
   `background-image:none` and draws its chevron in ::after — do not touch
   either. */
html.hsv-skin-next .task-status-filter-btn,
html.hsv-skin-next .orka-multi-select-btn {
    border: 1px solid var(--hsv-n-border);
    border-radius: var(--hsv-n-r-control);
    background-color: var(--hsv-n-bg);
    color: var(--hsv-n-fg);
}
html.hsv-skin-next .task-status-filter-btn:focus,
html.hsv-skin-next .orka-multi-select-btn:focus {
    outline: none;
    border-color: var(--hsv-n-sky);
    box-shadow: var(--hsv-n-ring);
}

/* ── .ui-textbox — its own island ─────────────────────────────────────────
   scss/controls.scss:345-355 already has radius 3px and a silver border, and
   is not covered by the theme classes at all. */
html.hsv-skin-next .ui-textbox input[type="text"],
html.hsv-skin-next .ui-textbox input[type="date"],
html.hsv-skin-next .ui-textbox input[type="password"] {
    border: 1px solid var(--hsv-n-border);
    border-radius: var(--hsv-n-r-control);
    outline-color: var(--hsv-n-sky);
}

/* ── .ui2-filter-card — !important, against another !important ────────────
   css/ui-2026.css:41 declares `border: 1px solid lightgray !important`. No
   specificity beats an important declaration, and @layer is not available in
   this stack, so an important is genuinely unavoidable here.

   Scoped to border-color rather than `border` so the important-vs-important
   fight covers the one property that matters and leaves ui-2026's `1px solid`
   in place.

   For the record: that !important was itself unnecessary —
   `body .ui2-filter-card .ui-input input` is (0,2,2) and already beat the
   theme's (0,2,1). It was cargo-culted, and it now forces this one. Do NOT
   conclude from this block that specificity is generally insufficient in this
   file — see the list in the header for the only other places it appears. */
html.hsv-skin-next .ui2-filter-card .ui-input input,
html.hsv-skin-next .ui2-filter-card .ui-select select {
    border-color: var(--hsv-n-border) !important;
    border-radius: var(--hsv-n-r-control);
    background-color: var(--hsv-n-bg);
}

/* ── Buttons ──────────────────────────────────────────────────────────────
   DO NOT set `display` here. See trap 2.

   And no `font-weight`: the DS button is 600, but across the legacy app that
   read as heavy rather than emphatic. Buttons keep their own weight. */
html.hsv-skin-next .btn {
    /* (0,2,1) vs bootstrap's .btn (0,1,0) and
       scss/calculatorsCustom.scss:138 `.btn{font-size:13px}` (0,1,0) */
    border-radius: var(--hsv-n-r-btn);
    transition: background-color .2s ease, border-color .2s ease,
                color .2s ease, box-shadow .2s ease;
}

/* scss/reset.scss kills `outline` on every button and link app-wide, so there
   is NO visible keyboard focus on buttons today. This is an accessibility fix
   as much as a cosmetic one. */
html.hsv-skin-next .btn:focus {
    box-shadow: var(--hsv-n-ring);
}

/* Primary, OUTSIDE a modal. scss/styles.scss:66-72 gives it
   `background-color:#118dcf; border:none; padding:10px 5px; display:block;
   text-align:center`, and :74-76 a silver box-shadow. Colour, radius and the
   glow change here — padding, display and text-align are left exactly as they
   are.

   `border-radius` is restated even though the base `.btn` rule above already
   sets it (line ~600): the main calculate button (#calc-btn) carries classes
   `calc-btn btn-primary btn-fixed`, with no plain `.btn`, so it never reaches
   that rule. */
html.hsv-skin-next .btn-primary {
    background-color: var(--hsv-n-sky);
    color: #FFFFFF;
    border-radius: var(--hsv-n-r-btn);
}
html.hsv-skin-next .btn-primary:not(.no-shadow) {
    /* (0,3,1) vs styles.scss:74's (0,2,0) — the silver glow is not in the new
       design language. */
    box-shadow: none;
}
html.hsv-skin-next .btn-primary:hover {
    /* (0,3,1) vs styles.scss:78's (0,2,0), which re-states #118dcf on hover */
    background-color: var(--hsv-n-sky-d);
    border-color: var(--hsv-n-sky-d);
}
html.hsv-skin-next .btn-primary[disabled],
html.hsv-skin-next .btn-primary[disabled]:hover,
html.hsv-skin-next .btn-primary.disabled,
html.hsv-skin-next .btn-primary.disabled:hover {
    /* styles.scss:83-89 uses `silver`; this is the token equivalent. */
    background-color: var(--hsv-n-disabled);
    color: var(--hsv-n-fg-4);
}

/* Primary, INSIDE a modal: the inversion is KEPT, not undone.
   scss/styles.scss:95-101 flips it to an outlined button via
       body .modal:not(.sub-calculator) .btn-primary:not(.blue-bg)   (0,4,1)
   That is a deliberate, long-standing legacy convention — a modal's primary
   action is outlined — and it happens to map cleanly onto the new design's
   `secondary` variant (white fill, #D0D3E2 border, navy text). So it is
   RE-COLOURED here, not unified with the filled primary above. Unifying it
   would flip the visual weight of every confirm button in the app, which is a
   behaviour change dressed up as a colour change.

   To beat (0,4,1) the gate has to ride along with the whole original chain:
   html + .hsv-skin-next + body + .modal + :not(.sub-calculator)
   + .btn-primary + :not(.blue-bg)  =  (0,4,3). */
html.hsv-skin-next body .modal:not(.sub-calculator) .btn-primary:not(.blue-bg) {
    background-color: #FFFFFF;
    color: var(--hsv-n-navy);
    border: 1px solid var(--hsv-n-border);
    box-shadow: none;
}
html.hsv-skin-next body .modal .btn-primary:hover {
    /* (0,4,2) vs styles.scss:105's `box-shadow: 0 0 5px #118dcf` at (0,3,1) */
    box-shadow: none;
    border-color: var(--hsv-n-navy);
    background-color: var(--hsv-n-tint-navy);
    color: var(--hsv-n-navy);
}
html.hsv-skin-next body .modal .btn-primary:focus {
    /* (0,4,2) vs styles.scss:109's (0,3,1), which FILLS the button blue on
       focus — so a keyboard user currently sees a colour change rather than a
       ring. Replace it with the ring. */
    background-color: #FFFFFF;
    color: var(--hsv-n-navy);
    box-shadow: var(--hsv-n-ring);
}
html.hsv-skin-next body .modal .btn-secondary {
    /* (0,4,2) vs styles.scss:137's (0,3,1) — legacy fills it #118dcf.
       White fill, not sky: it is a secondary action next to the modal's
       primary button, matching the in-control buttons above. */
    background-color: #FFFFFF;
    border-color: var(--hsv-n-sky);
    color: var(--hsv-n-sky);
}
html.hsv-skin-next body .modal .btn-secondary:hover {
    background-color: var(--hsv-n-tint-sky);
    border-color: var(--hsv-n-sky-d);
    color: var(--hsv-n-sky-d);
}

/* Danger — #d9534f/#d43f3a become --danger on a tinted fill, matching the
   danger variant in web/src/ui/Button.tsx. */
html.hsv-skin-next .btn-primary.btn-danger,
html.hsv-skin-next body .modal .btn-primary.btn-danger {
    background-color: #FFFFFF;
    color: var(--hsv-n-danger);
    border: 1px solid rgba(192, 53, 78, .3);
}
html.hsv-skin-next .btn-primary.btn-danger:hover,
html.hsv-skin-next body .modal .btn-primary.btn-danger:hover {
    background-color: var(--hsv-n-danger-bg);
    border-color: var(--hsv-n-danger);
    color: var(--hsv-n-danger);
    box-shadow: none;
}

/* In-control buttons — scss/controls.scss:35-54, :106-132, :152-167.
   Colour only here; their HEIGHT is set in the HEIGHT LOCKSTEP block above,
   because it has to match the field they sit against.

   Recoloured WHITE, not filled sky — these are secondary/utility actions
   (person lookup, subcalc, select…), and the new design reserves the filled
   sky for the single primary action on a screen (.btn-primary above). `color`
   and `border-color` are restated too: scss/controls.scss:42/108/159/473 paint
   these with `color: white` for a sky fill, which would be invisible text on
   the new white background. This is the same white/sky/bordered look the
   legacy `.btn-invert` variant already uses (below). */
html.hsv-skin-next .ui-control.ui-client button,
html.hsv-skin-next .ui-control .ui-button button,
html.hsv-skin-next .ui-control .ui-input-subcalc button,
html.hsv-skin-next .ui-control .ui-select-subcalc button,
html.hsv-skin-next .ui-button-input input[type="button"] {
    background-color: #FFFFFF;
    color: var(--hsv-n-sky);
    border-color: var(--hsv-n-sky);
    border-radius: var(--hsv-n-r-control);
    box-shadow: none;
}
html.hsv-skin-next .ui-control.ui-client button:hover,
html.hsv-skin-next .ui-control .ui-button button:not(.btn-invert):hover,
html.hsv-skin-next .ui-button-input input[type="button"]:hover {
    background-color: var(--hsv-n-tint-sky);
    border-color: var(--hsv-n-sky-d);
    color: var(--hsv-n-sky-d);
}
html.hsv-skin-next .ui-control .ui-button button.btn-invert,
html.hsv-skin-next .btn-primary.btn-invert {
    background-color: #FFFFFF;
    color: var(--hsv-n-sky);
    border: 1px solid var(--hsv-n-border);
}

/* `.rv-action .btn-group .btn { border-radius: 0 }` (scss/styles.scss:1-6,
   (0,3,0)) still beats the base .btn rule above for the group's inner corners
   — square where the two buttons meet is correct, it reads as one control.
   But the OUTER corners of a split button — #split-button (createDocument,
   e.g. calcDocument6111RV.html) and its uib-dropdown-toggle sibling — should
   round like every other next-skin button. The pattern recurs outside
   .rv-action too (e.g. depreciationEditItem.html's "הפק רווח הון", inside a
   modal, where the toggle carries no .btn class at all, only an inline
   style), so this keys off the literal #split-button id instead of the
   .rv-action ancestor or a .btn class. The toggle is DOM-first: in RTL that
   renders it on the RIGHT, with #split-button to its left, so the toggle
   rounds its right side and #split-button its left. `:has(+ #split-button)`
   picks the toggle out by its position, not its classes — it is what keeps
   this working for calcDocument1219ExplanationsRV.html (toggle also carries
   .btn-primary) and the depreciation modal (toggle carries neither .btn nor
   .btn-primary) alike. (0,4,1)/(1,2,1) beats both the (0,3,0) square-off
   above and the (0,2,1) .btn-primary rule earlier in this file. */
html.hsv-skin-next .btn-group > :first-child:has(+ #split-button) {
    border-radius: 0 var(--hsv-n-r-btn) var(--hsv-n-r-btn) 0;
}
html.hsv-skin-next .btn-group > #split-button {
    border-radius: var(--hsv-n-r-btn) 0 0 var(--hsv-n-r-btn);
}

/* ── Button height ────────────────────────────────────────────────────────
   Buttons stayed padding-derived through the earlier passes, which left them
   noticeably shorter than the 36px fields beside them — Bootstrap's `.btn` is
   ~34px, and the modal footer override (css/modal.css:38, `padding: 2px 10px`)
   is nearer 28px.

   `min-height`, not `height`: a button whose label wraps must still be able to
   grow, and several carry icons at 20px. <button> centres its own content box
   vertically in every browser regardless of `display`, so nothing needs to be
   done about `display: block` (see trap 2 — and do not add flex here).

   `.btn-xs` (75 uses) and `.btn-sm` (32 uses) are deliberately compact — grid
   row actions, inline links, the settings refresh — and are excluded rather
   than scaled. React's own `sm` is ~33px, so they are already close.

   `.wizard-navigation` is excluded as well, and for a different reason than
   size: that container is `pull-left`, i.e. FLOATED, and css/wizard.css:69-76
   sizes its buttons to fit a specific layout (`min-width: 100px`). A taller
   float there reserves more space and the content beside it — the depreciation
   items table — wraps around a column of empty space. Its buttons therefore
   stay exactly as legacy renders them. If another floated or width-critical
   button container turns up, it belongs on this list too.

   (0,4,1), which clears both Bootstrap's `.btn` (0,1,0) and the modal footer's
   `.modal.in .modal-dialog .modal-footer .btn` (0,4,0). */
/* NO `font-weight` here. The design system's own button is 600, but applied
   across the legacy app it read as heavy rather than emphatic — legacy buttons
   carry longer Hebrew labels in more places than the DS kit anticipates, and
   several sit side by side in footers where the weight compounds. Buttons keep
   whatever weight their own stylesheet gives them. */
html.hsv-skin-next .btn:not(.btn-xs):not(.btn-sm) {
    min-height: var(--hsv-n-ctl-h);
}
/* The `:not()`s are load-bearing, not copy-paste: the general rule above is
   (0,4,1) because of them, so this exclusion needs (0,5,1) to win. Written
   without them it is (0,3,1), loses, and the exclusion silently does nothing —
   which is exactly what happened on the first attempt. */
html.hsv-skin-next .wizard-navigation .btn:not(.btn-xs):not(.btn-sm) {
    min-height: 0;
}

/* DO NOT normalise `.btn-primary`'s padding here.
   ------------------------------------------------
   A previous revision set `padding-top/bottom: 9px` on it, to pull its natural
   40px (scss/styles.scss:66-72, `padding: 10px 5px` + `border: none`) down to
   the same 36px as a `.btn-default` beside it in a footer. It cost 2px of
   consistency and broke a real layout.

   Padding on `.btn` is CONTEXT-OWNED in this app: css/wizard.css:69-76 gives
   `.wizard-navigation .btn` a deliberate `min-width:100px; padding:7px 5px`
   and :84-87 tightens `.btn-invert` to `6px 5px`. A gated rule at (0,4,1)
   out-specifies all of those, so it silently re-sized the הוסף button inside
   `.wizard-navigation.pull-left` from ~34px to 41.6px — and because that
   container is FLOATED, a taller button reserves more space and the table
   beside it reflowed around a column of empty space.

   `min-height` is the right mechanism precisely because it only sets a floor:
   it never replaces a padding value some other stylesheet chose on purpose.
   Leave primary at its natural 40px. */

/* ── The tree-picker (קטגוריות לתצוגה) ─────────────────────────────────────
   app/views/templates/treeControl.html builds its trigger with INLINE styles:
       style="width:100%; height:31px; background-color:white; border:1px solid #000"
   and its dropdown panel with an inline `top: 32px`.

   Inline styles lose to nothing but `!important`, which is why every other
   rule in this file missed this control entirely and it kept both its 31px
   height and its black border under the new design. These four declarations
   are the ONLY place in this file where !important is used against an inline
   style rather than another !important.

   The alternative — editing treeControl.html to move those styles into a
   stylesheet — would be the better engineering fix, but it changes markup
   every legacy user renders. Not worth it for a skin. */
html.hsv-skin-next #treeControlWrapper > button {
    height: var(--hsv-n-ctl-h) !important;
    border: 1px solid var(--hsv-n-border) !important;
    border-radius: var(--hsv-n-r-control);
    color: var(--hsv-n-fg);
}

/* The panel hangs off the trigger's bottom edge: inline `top: 32px` was the
   31px button plus its border. Tracks the control height the same way. */
html.hsv-skin-next #treeControlWrapper > div {
    top: calc(var(--hsv-n-ctl-h) + 1px) !important;
}

/* ── The grid's Excel-export button ───────────────────────────────────────
   PRE-EXISTING BUG, fixed here rather than in legacy because the fix is only
   verified under this skin.

   `.grid .grid-action` (css/grid.css:61-71) floats over the grid's top-right
   corner at `position:absolute; top:0; right:0; z-index:10`. But Handsontable
   stacks its frozen panes far above that — `.ht_clone_top: 101`,
   `.ht_clone_left: 102`, `.ht_clone_corner: 103` — so the header paints over
   the button and it looks half-hidden behind the table.

   104 clears the corner clone and stays below Handsontable's own overlays
   (110, 200, 999+) so autocomplete editors and context menus still win. */
html.hsv-skin-next .grid-container .grid .grid-action,
html.hsv-skin-next .grid .grid-action {
    z-index: 104;
}

/* …and give it somewhere to sit. Raising the z-index only stopped the table
   painting OVER the button; the button was still laid on top of the header
   row, because this skin zeroes `.grid:not(.no-excel-btn)`'s `padding-top`
   (rule just below) while the action is pinned to `top: 0` of the same box.

   The padding opens a band above the table that the absolutely-positioned
   button occupies, so nothing overlaps and the two stop touching. Sized from
   the button itself (~28px: `padding: 5px` on the button, `.7em` on the
   action, a 1.5em glyph) plus a small gap.

   `.grid` (css/grid.css:43-48) is a bare `display: inline-block` utility,
   not something exclusive to Handsontable — it also lands on unrelated
   chips like the tab count/title pairing in the calc-map header, where an
   unconditional padding-top pushed the count onto its own line instead of
   sitting beside the title. `:has(hot-table)` (grid.css:11 — every real
   Handsontable wrapper contains one) keeps this band scoped to grids that
   actually have the export button, so it no longer leaks into every other
   `.grid` on the page. This is the one place the skin adds vertical space to
   a layout rather than just repainting it.

   The tighter base spacing lives here, not in css/grid.css: the legacy skin
   relies on grid.css's `padding-top: 15px` as the band the button sits in,
   and zeroing it there put the button on top of the header in the old design. */
html.hsv-skin-next .grid-container .grid:not(.no-excel-btn),
html.hsv-skin-next .grid:not(.no-excel-btn) {
    margin: 5px 0 5px 5px;
    padding-top: 0;
}

html.hsv-skin-next .grid-container .grid:not(.no-excel-btn):has(hot-table),
html.hsv-skin-next .grid:not(.no-excel-btn):has(hot-table) {
    padding-top: 20px;
}

/* ═══ ADORNMENT OFFSETS ════════════════════════════════════════════════════
   The companion to HEIGHT LOCKSTEP. Legacy positions every in-field icon with
   a hand-measured `top` derived from a 31px box; at 36px each is 2.5px out.

   Two treatments, and picking the wrong one is the trap:

     CENTRED   — where the offset parent is the <label>. `.ui-labelify` is
                 absolutely positioned and out of flow, so the label's height
                 IS the input's height, and 50% is exactly the field's centre.
                 These stop depending on control height entirely.

     MEASURED  — where the offset parent is TALLER than the input. Centring
                 there lands the icon in the middle of the caption instead of
                 the field. Only option is to keep the number and add 2.5px.  */

/* ── CENTRED ─────────────────────────────────────────────────────────────── */

/* The search magnifier — scss/controls.scss:243, `top: 6px`, 24 instances
   across 23 files. Single highest-value fix in this block.

   Scoped with `.ui-input` so it cannot reach the two re-flowed filter cards
   handled under MEASURED below — those match `.ui-control .ui-search` too, and
   an unscoped centring rule here would beat their (0,5,x) overrides only
   sometimes, producing a bug that depends on which card you are looking at. */
html.hsv-skin-next .ui-control .ui-input.ui-search .ui-button {
    top: 50%;
    transform: translateY(-50%);
}

/* scss/controls.scss:94 (`top:6px`) and :370 (`top:6px`) — the in-field clear
   X and the .ui-textbox cross. Both live inside the label. */
html.hsv-skin-next .ui-control .input-times .fa.fa-times,
html.hsv-skin-next .ui-textbox .cross {
    top: 50%;
    transform: translateY(-50%);
}

/* css/calculators.css:707 (`.fa-percent`, top:8px) and :715
   (`.input-fonticon:before`, top:5px). The percent sign is a real <i> inside
   the label, which is why it needs this while the currency and datepicker
   SPRITES do not — those are `background-position: … center`. */
html.hsv-skin-next .ui-control .ui-input label .fa-percent,
html.hsv-skin-next .ui-control .custom-checkbox .fa-percent,
html.hsv-skin-next .input-fonticon:before {
    top: 50%;
    transform: translateY(-50%);
}

/* css/calculators.css:889-901 — `.input-icon` (top:6px) and its .fa-times /
   .fa-refresh variants, which set only `left` and so need nothing here. */
html.hsv-skin-next body .ui-control .input-icon {
    top: 50%;
    transform: translateY(-50%);
}

/* css/settings.css:876-883 — the sent-documents clear X, `top: 15px`.
   Centring is right here because its parent `.sentdoc-client-input-wrapper` IS
   `position: relative` (settings.css:866) and wraps ONLY the input. Note this
   rule replaces controls.scss:88's `top:30px` on that card by specificity —
   see the comment at settings.css:875. */
html.hsv-skin-next .sentdoc-filter-card .ui-control.ui-client .sentdoc-client-clear {
    top: 50%;
    transform: translateY(-50%);
}

/* ── MEASURED (+2.5px) ───────────────────────────────────────────────────── */

/* css/ui-2026.css:60-62 — `top: 14px`. The input here carries
   `margin-top: 7px !important` (ui-2026.css:43), so the label box is pushed
   down and 50% would not be the field's centre. */
html.hsv-skin-next .ui2-filter-card .ui-control .ui-search .ui-button {
    top: 16.5px;
}

/* css/entitiesManagement.css:52-54 (`top:32px`) and :63-65 (`top:13px`).
   These two cards re-flow `.ui-labelify` to STATIC positioning
   (entitiesManagement.css:13-20), so the caption is in normal flow and the
   label is caption+input tall — roughly 22px taller than the field. Centring
   would put the magnifier in the caption. The comment at :51 documents both
   the 22px push and the specificity ladder; the selectors here mirror it. */
html.hsv-skin-next .calculator-dueDatesManagement-page .due-dates-filter-card .ui-control .ui-search .ui-button {
    top: 34.5px;
}
html.hsv-skin-next .calculator-clientMessageCampaigns-page .due-dates-filter-card .ui-control .ui-search .ui-button {
    top: 15.5px;
}

/* `.info-sign` — css/calculators.css:541-548 and :550-553. The ONLY
   bottom-anchored adornment in the app, so it drifts the OPPOSITE way from
   everything above and its two variants need opposite corrections. */
html.hsv-skin-next .info-sign {
    bottom: 13.5px;              /* was 11px */
}
html.hsv-skin-next .ui-input-with-subcalc .info-sign {
    bottom: auto;                /* the override flips it to top-anchored */
    top: 7.5px;                  /* was 5px */
}

/* css/main.css:523-527 — the default-customer clear X, `top: 5px`. Centred
   rather than measured: main.css:513 explicitly makes this `.ui-input`
   `position: relative`, so the offset parent is the field's own box.

   This component is still on screen for a shell-only user: the React
   ClientContextBar replaces it only when hsv.crmNext is on (that is what
   swaps the whole route for a React screen), and the two preferences are
   independent. Its own input and button both take --hsv-n-ctl-h from the
   lockstep rules above, so they stay matched — the bar just gets taller. */
html.hsv-skin-next .default-customer .ui-control.ui-client .fa.fa-times {
    top: 50%;
    transform: translateY(-50%);
}

/* ── Dropdown panels anchored to the trigger ─────────────────────────────── */

/* css/confirmation-status-dropdown.css:212-221 and :319-328 — menus at
   `top: 78%`, which overlapped a 31px trigger by 6.8px and a 36px one by
   8.4px. `100%` is what was meant: flush under the trigger, height-agnostic. */
html.hsv-skin-next .task-status-dropdown-menu,
html.hsv-skin-next .orka-multi-select-menu {
    top: 100%;
}

/* css/entitiesManagement.css:94-96 — panel below a trigger PLUS its label,
   `top: 56px !important`. The !important is theirs, so it has to be matched. */
html.hsv-skin-next .calculator-dueDatesManagement-page .due-dates-filter-card #treeControlWrapper > div {
    top: 61px !important;
}

/* ── Deliberately NOT height-corrected ──────────────────────────────────────
   - css/grid.css:105-115 `.hot-field` — a clone of the input geometry that is
     `position:absolute; top:0; right:98px` OVER a Handsontable cell.
     Handsontable measures its own cell geometry in JS; growing this
     desynchronises the overlay from the grid. Hard no.
   - css/main.css:432 header search — self-consistent 30/31px island, and the
     legacy `.header` is display:none under this shell anyway.
   - css/settings.css:857-862 `.sentdoc-filter-card .ui-client button
     { margin-top: -36px }` — a hand-measured PULL-UP, not a centred offset,
     so it fails visibly rather than subtly. It also already contains the
     literal `36`, which reads as "already migrated" to anyone skimming: it is
     not. Confirm on screen before changing it; arithmetic alone (-43px) is a
     starting point, not an answer.
   - templates/defaultCustomer.html:32 has an INLINE
     `style="…top:5px"` spinner. Inline styles beat everything but !important;
     it is a transient spinner in one template, so the 2.5px drift is accepted
     rather than fought.
   - scss/controls.scss:88 `.ui-control.ui-client .fa.fa-times
     { left:55px; top:30px }` — `span.ui-input` and `span.customer-action` are
     NOT positioned and the X is a sibling of the label, so the offset parent
     is somewhere further up and `top:30px` is empirical. Left alone pending a
     browser check; the two cards that actually use a clear X
     (.sentdoc-client-clear, .default-customer) are both handled above.
   - `.ui-datetime` timepicker (scss/controls.scss:221-234) and
     `.ui-input.ui-button button` (:106-132) — 2 instances each, padding- or
     underline-styled with no height of their own. They will sit short. Fix
     only if the visual pass says it reads wrong. */

/* ═══ THE SECTION NAVIGATOR (calc-map-navigator) ═════════════════════════════
   app/directives/calcMapNavigator.js / app/views/templates/calcMap.html — the
   vertical list of section titles beside a big calculator (the 1301 annual
   report and nine siblings), and its TABS-mode alternative. Ported from
   heshev-design-system/preview/legacy-override.css section 11 — the design
   card there names this component "the biggest blue mass on a legacy screen"
   and the whole card's thesis is ONE filled blue per screen (the primary
   action) plus focus rings and links; navy for headings and active markers;
   everything else cool neutrals.

   Two mutually exclusive renderings, chosen by
   displayService.settings.titleViewType:

     LIST  .calc-map > .solid-border > .dashed-border > a[.active] > .calc-steps
                                                                    > .step-label
                                                                    > .step-sign (two <i>, the dot)
     TABS  .calc-map > .calc-map-tabs > uib-tabset (Bootstrap .nav-tabs)

   Both consumer families are in scope: the 10 report screens wrap this in
   `.calc-side-titles.many-titles` (calc-anchors.css's .many-titles block
   applies), and the customer/entity screens (editCustomerController,
   newCustomerController, companyController, EmployedController and others)
   use it bare, picking up css/new-customer.css:219-226 instead.

   THREE THINGS THAT SHAPE EVERY RULE BELOW
   -----------------------------------------
   1. calc-anchors.css:133 `.calc-map .solid-border .calc-map a` is a DEAD
      SELECTOR — it requires a `.calc-map` inside `.solid-border`, which the
      template never nests. Its `color:#428bca` never applies. The item text
      colour today is inherited from scss/reset.scss:33 `body a{color:#118dcf}`
      at (0,0,2). A rule here that sets everything BUT color would silently
      keep every legacy-blue link — hence `color` is explicit on the row rule
      below, not left to inheritance.
   2. Font size is em-based and compounds: .step-label is .8em, .7em under
      .many-titles (calc-anchors.css:49), and .calc-map.h-small
      (calcMapNavigator.js:23, viewport < 800px tall) multiplies by .85 again
      — ~11px, or ~9.5px with h-small. An absolute px ends the compounding.
   3. `direction` is inconsistent across consumers: scss/reset.scss:23 sets
      html,body to ltr; .many-titles .solid-border is ltr while its own
      .dashed-border is rtl; new-customer.css:219 sets `.new-customer .calc-map`
      to rtl. `border-inline-start` would resolve to opposite physical sides on
      different screens, so every side below is PHYSICAL: border-right is the
      reading-start edge for Hebrew, and what the design card itself shows.

   THE PANEL'S HEIGHT — the one place this block touches layout on purpose
   -------------------------------------------------------------------------
   `.solid-border` (and `.calc-map-tabs`) is `position:fixed; height:calc(100%
   - 210px)` — viewport-tall, regardless of how many sections exist. Painting
   it as a card without also fixing this leaves a tall empty coloured column
   below the last row. `height:auto; max-height:calc(100% - 210px)` keeps the
   original sizing INTENT (leave room for the header and footer chrome) while
   letting the card end where the content does, and still caps it so a long
   list scrolls inside the card rather than growing off screen.

   THE PANEL'S WIDTH — right-edge anchored, width is the only knob
   ---------------------------------------------------------------------------
   `.solid-border`/`.calc-map-tabs` is `position:fixed` with `left`/`right`/
   `margin-left` all left unset (auto/0). Measured directly against a real
   render (not derived from the CSS2.1 abspos algorithm — this exact
   interaction of a `position:fixed` descendant of a floated, non-positioned,
   RTL-flipped ancestor chain did not match that algorithm's plain reading in
   testing, and is being treated here as an empirical fact rather than a
   proven derivation): with `direction:rtl` set on the element itself (below),
   its rendered RIGHT edge locks to `.calc-map`'s own right edge regardless of
   `width`, and `margin-left` has NO effect on where it lands — only `width`
   moves the LEFT edge, symmetrically, as `.calc-map`'s-right-edge − width.
   `margin-right:0` still has to be stated (see below), but not because it
   participates in placement the way the name suggests.

   This replaces an EARLIER (WRONG) model of this same fix, which assumed
   `left` was pinned via a measured "static position" and `margin-left` set
   the offset from it — that reasoning happened to produce the right answer
   at the ONE width (140px) it was tested against, by coincidence, then broke
   silently the moment width changed (this was caught only when a real width
   increase was requested here and the box did not move where the old
   reasoning predicted).

   Legacy's OWN unmodified `.many-titles .calc-map .solid-border` is
   `width:210px; margin-right:-45px` (calc-anchors.css:28-31), and separately
   `.calc-map-tabs` gets `width:165px` with no margin override (:33-35) —
   legacy's own instinct was ALSO "make this one wider for the many-titles
   case", just via a fragile, direction-sensitive margin trick rather than a
   plain `width`. This block keeps that same instinct — a `.many-titles`-
   scoped width override further down — with none of the fragility, since
   `margin-left` here is inert and there is no over-constrained equation to
   land on the wrong side of.

   `.dashed-border` fills the corrected host at `width:100%` with BOTH
   margins pinned to 0 — a plain in-flow block, unlike its `position:fixed`
   parent, so it stays exactly as wide as that parent regardless of what
   width the parent ends up with, in either scope.

   THE CARD IS PAINTED ON `.solid-border`, NOT `.dashed-border` — reported
   as a stray inner scrollbar on report screens where every row was already
   visible. `.solid-border` is the scroll host (`overflow-y:auto;
   max-height:calc(100% - 210px)`); an EARLIER version painted the
   background/border/radius on the child `.dashed-border` instead, which
   sits inside that scroll host in normal flow with `height:auto`. Border-box
   still makes a bordered element exactly as wide as it says, but height is
   different: adding `border:1px solid …` to `.dashed-border` adds 2px to
   ITS OWN rendered height on top of the rows it contains, and `.solid-
   border`'s `max-height` was never widened to match, so the scroll host's
   content became 2px taller than its cap for every screen using this
   component, regardless of row count — a permanent, content-independent
   2px of scrollable overflow. Painting the card on `.solid-border` itself
   instead removes the double-accounting: the border is now part of the
   SAME box the scroll math is computed against, exactly like tabs mode
   already does below ("one element does both jobs"). `overflow-y:auto`
   still clips to `.solid-border`'s own `border-radius` with no separate
   `overflow:hidden` needed — a non-`visible` overflow value clips
   descendants to the box's own rounded shape. `.dashed-border` keeps
   `border:0` only to cancel legacy's own `border-left:dashed 2px …`
   (calc-anchors.css:125), which would otherwise still show through.

   THE ACTIVE MARKER — replaced, not recoloured
   ---------------------------------------------
   Legacy marks the current section with a filled circle
   (.step-sign .far.fa-circle, calc-anchors.css:162, color:#428bca) sitting on
   a dashed line (.dashed-border). The design replaces the whole timeline
   metaphor with a 3px sky bar on the row's trailing edge. `.step-sign` is
   hidden outright — with its parent gone, the (0,5,3)/(0,7,0) selectors
   further up this file and in calc-anchors.css that toggle the circle's
   `display` have nothing left to act on and need no counterpart here. Since
   the dot is gone, the surface-repaint list higher in this file no longer
   lists `.calc-map .step-sign` (it used to, to give the dot an opaque ground
   masking the dashed line behind it) — both are dead together.

   NOTHING HERE NEEDS !important. The gate (`html.hsv-skin-next body …`) adds
   one class and one element over the bare legacy selectors, which is enough
   headroom against every rule this block has to beat — see the per-rule
   comments for the specificity ladder. `print.css:89`
   `body.print-version .calc-map{display:none}` is untouched: this block never
   sets `display` on `.calc-map` itself, so printing still hides the whole
   navigator exactly as before. */

/* The card AND scroll host, LIST MODE, combined — see the width note above
   for placement and the card-paint note above for why painting lives here
   rather than on the child `.dashed-border`. calc-anchors.css:69 `.calc-map
   .solid-border, .calc-map .calc-map-tabs{width:150px;…height:calc(100% -
   210px);position:fixed}` is (0,2,0); the .many-titles variant at :28-31
   (`width:210px;margin-right:-45px`) is (0,3,0). This is (0,3,2).

   `width:140px; margin-right:0` REPLACE the legacy width/margin pair
   entirely rather than adding to it. No `margin-left` here — see the width
   note above, it does nothing for this element. `margin-right:0` still has
   to be stated explicitly: CSS resolves per PROPERTY, so `.many-titles
   .calc-map .solid-border{margin-right:-45px}` (calc-anchors.css:28-31)
   would keep applying to just that one property otherwise. Whether THAT
   property is actually load-bearing for placement here (per the width note,
   evidence points to no) or only for the 'right' side of an equation nothing
   reads, it costs nothing to pin it and removes one more unknown.

   `direction:rtl` is the SCROLLBAR side, not text direction — this element
   has no text of its own. A browser puts a scrolling box's native scrollbar
   on its "end" edge as seen in ITS OWN `direction`, and `.many-titles
   .solid-border{direction:ltr}` (calc-anchors.css:7-9) puts this one's
   scrollbar on the far/outer edge of the whole sidebar, away from the
   calculator content beside it. Flipping it to `rtl` moves the scrollbar to
   the inner edge, beside the content — and, per the width note above, is
   ALSO what makes this element's own right edge lock to `.calc-map`'s right
   edge in the first place; the two effects share one cause. The child
   `.dashed-border` already sets its OWN `direction:rtl` for its text
   (calc-anchors.css:11-13, untouched), so nothing here affects reading
   order. */
html.hsv-skin-next body .calc-map .solid-border {
    background-color: var(--hsv-n-sunken);
    border: 1px solid var(--hsv-n-border-mid);
    border-radius: var(--hsv-n-r-card);
    direction: rtl;
    height: auto;
    margin-right: 0;
    max-height: calc(100% - 210px);
    overflow-x: hidden;
    overflow-y: auto;
    width: 140px;
}

/* WIDER for the report screens. Legacy's own `.many-titles .calc-map
   .solid-border{width:210px}` (calc-anchors.css:28-31) already tried to make
   this case wider than the base 140px — the em-chain that made 13px labels
   necessary (see point 2 in the header note) is exactly what makes more
   width valuable here too: Hebrew titles at 13px in a 140px card wrap onto
   2-3 lines routinely. 175px is chosen, not legacy's 210px, because of the
   real ceiling next to it — `.calc-tabs` is `width:calc(100% - 190px)` at
   `@media (min-width:1350px)` (calculators.css:89-91) while `.calc-side-
   titles` is only `width:180px` there (:97), a 10px gutter between the two
   that a real render shows extends further (~35-40px of true dead space
   past `.calc-side-titles`'s own edge before real form content starts) —
   measured, not assumed, after the width-vs-position surprise above. 175px
   leaves a comfortable margin inside that budget; the true ceiling measured
   at ~189px before touching real content. (0,4,2) vs the .many-titles
   variant this replaces at (0,3,0). */
html.hsv-skin-next body .many-titles .calc-map .solid-border {
    width: 175px;
}

/* The row list, LIST MODE. Unpainted now — see the card-paint note above;
   this is plain in-flow content inside `.solid-border`'s scroll box.
   `width:100%` of the host above — whatever width that resolves to, base or
   the wider .many-titles case — with BOTH margins at 0, deterministic
   regardless of `.solid-border`'s `direction`. `border:0` cancels legacy's
   `border-left:dashed 2px #E8E9E9` (calc-anchors.css:125), which this
   element would otherwise still show since nothing else here zeroes it.
   Beats calc-anchors.css:122-126 (0,2,0) and the .many-titles variant :37-42
   (`width:151px;margin-left:10px`, (0,3,0)) at (0,3,2). */
html.hsv-skin-next body .calc-map .dashed-border {
    border: 0;
    height: auto;
    margin-left: 0;
    margin-right: 0;
    width: 100%;
}

/* The card, TABS MODE — painted directly, pinned to `.calc-map`'s own box
   the same way as the list-mode host above, and for the same reason: legacy
   gives it `width:165px` (calc-anchors.css:33-35) with no margin override at
   all, yet it shows the SAME right-edge-anchored, margin-left-is-inert
   behaviour as `.solid-border` (measured) — confirming this is a property of
   the `direction:rtl` + fixed-position-inside-a-float combination itself,
   not something particular to `.solid-border`'s specific legacy margin.
   Same (0,3,2) ladder as the host above; height/scroll fix and paint
   combined on one element here, same as list mode's `.solid-border` now
   does (see the card-paint note there for why splitting paint onto a
   nested child caused a stray 2px scrollbar).

   No `margin-right:0` needed here, unlike `.solid-border` above: legacy
   never gives `.calc-map-tabs` a margin-right at all (only `.solid-border`
   gets the `.many-titles`-specific `-45px`, calc-anchors.css:28-31), so
   there is no stray per-property value left to keep winning.

   `direction:rtl` — same scrollbar-side fix as `.solid-border` above.
   calc-anchors.css:77-80 sets `.calc-map .calc-map-tabs{direction:ltr}`
   UNCONDITIONALLY (not only under .many-titles), so every tabs-mode use has
   this. The inner `<ul class="nav-tabs">` already has its own
   `direction:rtl` (:82-84, for the tab labels), untouched. */
html.hsv-skin-next body .calc-map .calc-map-tabs {
    background-color: var(--hsv-n-sunken);
    border: 1px solid var(--hsv-n-border-mid);
    border-radius: var(--hsv-n-r-card);
    direction: rtl;
    height: auto;
    max-height: calc(100% - 210px);
    overflow-x: hidden;
    overflow-y: auto;
    width: 140px;
}

/* WIDER for the report screens — same reasoning and same 175px as the list-
   mode host above. (0,4,2) vs the .many-titles variant it replaces at
   calc-anchors.css:20-26, `.many-titles .calc-map .solid-border, .calc-map
   .calc-map-tabs{width:210px;…}` (0,3,0). */
html.hsv-skin-next body .many-titles .calc-map .calc-map-tabs {
    width: 175px;
}

/* The step box. Rows are flush now, separated by the row's own hairline
   border, so the old between-row margin goes. Beats calc-anchors.css:44
   `.many-titles .calc-map .calc-steps{width:180px;margin-bottom:5px}` (0,3,0),
   :128 `.calc-map .calc-steps{width:150px;margin-bottom:20px}` (0,2,0), and
   the `@media (max-width:1367px) .calc-map div.calc-steps` rule (0,2,1). This
   is (0,3,2). */
html.hsv-skin-next body .calc-map .calc-steps {
    margin-bottom: 0;
    width: auto;
}

/* The row. `color` is explicit — see point 1 above; without it the link stays
   legacy #118dcf. `cursor:pointer` is a genuine (if small) fix: no rule in
   calc-anchors.css that actually matches ever set it. (0,3,3) here, against
   the inherited `body a{color:#118dcf}` at (0,0,2) and the dead (0,3,1) rule
   at calc-anchors.css:133 that can never match this markup anyway. */
html.hsv-skin-next body .calc-map .dashed-border a {
    border-right: 3px solid transparent;
    border-top: 1px solid var(--hsv-n-border-sub);
    color: var(--hsv-n-fg-2);
    cursor: pointer;
    display: block;
    font-weight: 400;
    line-height: 1.3;
    padding: 8px 12px;
    text-decoration: none;
    transition: background-color .12s ease;
}
/* No `.lg-navhead` equivalent exists in this markup (see the header note),
   so the first row sits directly under the card's own top border; without
   this it would show its own hairline immediately below that, reading as a
   doubled line. No radius needed here — `.dashed-border`'s own
   `overflow:hidden` already clips every row's corners to the card's shape. */
html.hsv-skin-next body .calc-map .dashed-border a:first-child {
    border-top: 0;
}
html.hsv-skin-next body .calc-map .dashed-border a:hover {
    background-color: var(--hsv-n-tint-navy);
    color: var(--hsv-n-fg);
}
/* scss/reset.scss:5 `html body button, …, a:focus{outline:none}` kills focus
   app-wide, so this needs its own replacement — but NOT a 4-sided `outline`
   or `box-shadow` ring: `outline` cannot be drawn on one side only, and a
   full box around a 150px-wide row reads as a stray rectangle rather than
   the row lighting up. Reusing the row's OWN one-sided marker (the
   `border-right` every row already reserves, transparent, above) plus the
   hover tint keeps every visible state — hover, focus, active — expressed
   the same way: colour and a right-edge bar, never a box.

   `:focus-visible`, NOT `:focus` — reported: clicking a row (which
   `du-smooth-scroll` jumps to) leaves that `<a>` focused, and scrolling then
   moves `.active` elsewhere via `du-scrollspy`, so `:focus`'s row and
   `.active`'s row light up as two different "selected-looking" rows at
   once. `:focus-visible` only matches keyboard navigation (Tab), not a
   mouse click — a click already got its feedback from the jump-scroll
   itself, so it needs no lingering marker, and this is precisely the
   distinction `:focus-visible` exists to draw. Keyboard users still get the
   bar; nothing here regresses that. */
html.hsv-skin-next body .calc-map .dashed-border a:focus-visible {
    background-color: var(--hsv-n-tint-navy);
    border-right-color: var(--hsv-n-sky);
    outline: none;
}
/* Same specificity as `a:hover` above — (0,4,3) either way — so it relies on
   coming AFTER it in source order to win the tie. That is deliberate, not an
   oversight: hovering the already-active row should keep its active look
   rather than flash the hover tint, mirroring how the ported design source
   orders its own `nav a:hover` / `nav a[aria-current]` pair. */
html.hsv-skin-next body .calc-map .dashed-border a.active {
    background-color: var(--hsv-n-surface);
    border-right-color: var(--hsv-n-sky);
    color: var(--hsv-n-fg);
    font-weight: 600;
}

/* The label. Absolute px, not em — point 2 above. Beats
   .many-titles .calc-map .step-label (:49, (0,3,0)),
   .new-customer .calc-map .step-label (new-customer.css:223, (0,3,0)) and the
   base .calc-map .step-label (:139, (0,2,0)) at (0,3,2). text-align is
   PHYSICAL right — point 3 above. */
html.hsv-skin-next body .calc-map .step-label {
    display: block;
    font-size: 13px;
    text-align: right;
    width: auto;
}

/* The dot. Hiding the parent is enough — see the header note. Beats
   .many-titles .calc-map .step-sign (:54, (0,3,0)) and the base rule (:148,
   (0,2,0)) at (0,3,2). */
html.hsv-skin-next body .calc-map .step-sign {
    display: none;
}

/* TABS mode — the row wrapper. Bootstrap's OWN default
   `.nav-tabs>li{float:left;margin-bottom:-1px}` (css/libs/bootstrap.min.css)
   is never touched by calc-anchors.css or by the `li a` rule below — both
   only ever style the <a>, never the <li> that carries this margin. It is
   meant for classic bordered tabs, where the active tab's bottom border
   needs to overlap the content pane's border directly beneath it; here the
   pane is empty and the tabs stack vertically, so it is dead weight, and
   `margin-bottom:-1px` on a FLOATED element is exactly that: floats pull
   each other by their margins, so five stacked `<li>`s report a `clientHeight`
   4px shorter than without it, once the four -1px gaps between them collapse.
   That is not merely cosmetic — Chromium's `scrollHeight` measures the same
   floats' scrollable-overflow extent WITHOUT applying that pull-together,
   so `.calc-map-tabs` (the scroll host, `overflow-y:auto` above) ends up with
   `scrollHeight` a few px TALLER than its own `clientHeight`, and shows a
   permanent scrollbar for a tab list that plainly fits — reported on a
   5-tab screen where nothing was remotely close to the `max-height` cap.
   `margin:0` here, on the `<li>` itself, is what the `li a` rule below
   could never reach. Same (0,3,3) ladder as `li a`'s (0,3,4) below —
   element, not class, on both sides — beating the bare bootstrap.min.css
   rule easily. */
html.hsv-skin-next body .calc-map .calc-map-tabs li {
    margin: 0;
}

/* TABS mode — the row itself. Shared layout for BOTH states first —
   calc-anchors.css:90-99
   `.calc-map .calc-map-tabs li a{padding:6px 8px 8px 3px;margin:1px;
   border:none;font-size:14px;letter-spacing:.5px}` is (0,2,2) (li and a are
   elements, not classes, here); this is (0,3,4). The edge-bar border-right is
   ALSO declared here, transparent, on BOTH states — not only on
   `li:not(.active)` as a first pass had it. calc-anchors.css:90-99's
   `border:none` sets border-STYLE to none for every tab; a later rule that
   only touches `li.active a{border-right-color:…}` changes a colour with no
   style to paint it against, so the active tab's bar silently never renders.
   Declaring the transparent 3px border here, once, for every tab, is what
   makes the later colour-only override on the active state actually visible.
   `font-size:13px` matches the list row's own `.step-label` — the two modes
   are meant to read as the same component, and legacy's `14px` here was the
   one place that had drifted from it. */
html.hsv-skin-next body .calc-map .calc-map-tabs li a {
    border-radius: 0;
    border-right: 3px solid transparent;
    font-size: 13px;
    letter-spacing: normal;
    margin: 0;
    padding: 8px 12px;
}
/* Paint. calc-anchors.css:106-119 fills every INACTIVE tab solid #118dcf —
   a large blue mass by the same rule this whole block follows. (0,4,4) here
   against its (0,3,2). */
html.hsv-skin-next body .calc-map .calc-map-tabs li:not(.active) a {
    background-color: transparent;
    border-top: 1px solid var(--hsv-n-border-sub);
    box-shadow: none;
    color: var(--hsv-n-fg-2);
}
/* Same one-sided reasoning as the list row's :focus-visible above — no
   4-sided outline, just the tab's own reserved right-edge bar plus a tint,
   and `:focus-visible` rather than `:focus` for the same reason: a mouse
   click needs no lingering marker once it has already set `.active`.
   calc-anchors.css:101-104 `…li a:focus,…:hover{border:none}` is untouched
   by this: it targets the `border` SHORTHAND, this only ever touches
   `border-right-color`. Declared BEFORE `li.active a`, which is also
   (0,4,4): the active tab must keep its own look when it also happens to be
   focused, the same tie-break choice the list row makes against its own
   :hover/:focus-visible (see the comment there). */
html.hsv-skin-next body .calc-map .calc-map-tabs li a:focus-visible {
    background-color: var(--hsv-n-tint-navy);
    border-right-color: var(--hsv-n-sky);
    outline: none;
}
html.hsv-skin-next body .calc-map .calc-map-tabs li.active a {
    background-color: var(--hsv-n-surface);
    border-right-color: var(--hsv-n-sky);
    color: var(--hsv-n-fg);
    font-weight: 600;
}
/* Bootstrap's `.nav-tabs{border-bottom:1px solid #ddd}` draws a stray
   horizontal hairline across what is here a VERTICAL strip. (0,4,2) vs its
   (0,1,0). */
html.hsv-skin-next body .calc-map .calc-map-tabs .nav-tabs {
    border-bottom: 0;
}

/* ── Calculator tab strips ────────────────────────────────────────────────
   `.calc-tabs` — the uib-tabset row that heads a multi-section calculator
   (הצהרת הון / 1219, 6111, ורקות and ~30 more). Restyled to React's `Tabs`,
   `variant="underline"` — the same component the customers screen puts above
   its table (web/src/ui/Tabs.tsx), spec'd in the kit as `.tabs`/`.tab`
   (heshev-design-system/ui_kits/heshev-financial/styles.css:215-224):

       strip   flex, gap 4px, 1px bottom border
       tab     10px 16px, 14px/500, --fg-2, 2px transparent bottom border
       hover   navy text
       active  navy text, bold, navy bottom border

   WHAT IT REPLACES, and why it is the whole strip rather than a recolour.
   calculators.css:399-433 paints EVERY tab a solid #118dcf with white text
   and gives only the ACTIVE one a white fill — the inverse of every other
   selected state in the new design, and by area the largest block of legacy
   blue left on a calculator. There is no colour substitution that fixes
   that; the geometry (fills, 4px radii, bordered boxes) has to go with it.

   Deliberately NOT included:
     - `.calc-map .calc-map-tabs` — the SIDE navigator's tabs mode. Already
       restyled as a vertical list above; it is a different component that
       merely shares Bootstrap's class names. Every selector here is anchored
       on `.calc-tabs`, which that strip is not inside.
     - `.customer-wrapper` / `.modal-dialog` tab strips (customers.css:220,
       new-customer.css:75) — icon-over-label tabs on a blue ground, a
       different component with its own layout. Left for their own pass.
     - The standalone tabsets that are not inside a `.calc-tabs` at all —
       dueDatesManagement's `.orkot` (dueDatesManagement.html:98) is the one
       that matters, since calculators.css gives it tab-content budgets that
       LOOK like the ones below. It keeps its legacy strip; see the closing
       note of the HEIGHT LOCKSTEP block.

   SPECIFICITY. Two legacy rules set the floor:
     calculators.css:399  .inner-calculator-content .calc-tabs.original-tabs
                          .nav-tabs li a.nav-link               (0,4,2)
     calculators.css:2-20 body.calculator-calcDocument1219-page … same tail,
                          inside @media, font-size only         (0,5,3)
   Media queries add nothing to specificity, so the second is the one to beat
   and (0,5,3) is the bar. Hence the doubled selector lists below: the plain
   `.calc-tabs` arm (0,4,4) covers every other calculator, and the
   `.calc-tabs.original-tabs` arm (0,5,4) is what outranks the 1219 block.
   Both are needed — dropping either leaves one family of screens behind. */

/* The strip. `nav-justified` stretched the tabs into equal table-cells across
   the full width, which is why 1219 needed three media queries stepping the
   font down to 0.7em to make four long Hebrew headings fit. React's strip is
   natural-width and start-aligned, and scrolls when it runs out of room — so
   the font can stay at one size and the headings stay readable. Restating
   `border-bottom` is required: `.nav-tabs.nav-justified` (0,2,0) explicitly
   zeroes the `.nav-tabs` hairline that the underline design needs back. */
html.hsv-skin-next body .inner-calculator-content .calc-tabs .nav-tabs,
html.hsv-skin-next body .inner-calculator-content .calc-tabs.original-tabs .nav-tabs {
    border-bottom: 1px solid var(--hsv-n-border-mid);
    display: flex;
    flex-wrap: nowrap;
    gap: 4px;
    margin: 0;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 0;
    /* Same treatment React gives this strip: the scroll affordance is the
       content sliding, not a scrollbar track parked under a 2px underline.
       web/src/styles/extensions.css:284 (`.hsv-scroll-x-hidden`). */
    scrollbar-width: none;
}

html.hsv-skin-next body .inner-calculator-content .calc-tabs .nav-tabs::-webkit-scrollbar,
html.hsv-skin-next body .inner-calculator-content .calc-tabs.original-tabs .nav-tabs::-webkit-scrollbar {
    display: none;
}

/* The items. Bootstrap floats them (`.nav-tabs>li{float:left}`) and
   `nav-justified` gives them `display:table-cell;width:1%`; inside a flex
   container the display value is blockified for free, but the 1% is not —
   it has to be cleared by hand or every tab collapses to its padding.
   `margin-bottom:-1px` is Bootstrap's own, and is what lets the active tab's
   2px underline sit ON the strip's hairline instead of below it. */
html.hsv-skin-next body .inner-calculator-content .calc-tabs .nav-tabs li,
html.hsv-skin-next body .inner-calculator-content .calc-tabs.original-tabs .nav-tabs li {
    flex: 0 0 auto;
    float: none;
    margin: 0 0 -1px;
    width: auto;
}

html.hsv-skin-next body .inner-calculator-content .calc-tabs .nav-tabs li a.nav-link,
html.hsv-skin-next body .inner-calculator-content .calc-tabs.original-tabs .nav-tabs li a.nav-link {
    background-color: transparent;
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    color: var(--hsv-n-fg-2);
    font-size: 14px;
    font-weight: 500;
    margin: 0;
    padding: 10px 16px;
    transition: color .15s ease, border-color .15s ease;
    white-space: nowrap;
}

html.hsv-skin-next body .inner-calculator-content .calc-tabs .nav-tabs li a.nav-link:hover,
html.hsv-skin-next body .inner-calculator-content .calc-tabs.original-tabs .nav-tabs li a.nav-link:hover {
    background-color: transparent;
    border-bottom-color: transparent;
    color: var(--hsv-n-navy);
}

/* `:focus-visible`, not `:focus` — a mouse click already shows itself by
   making the tab active, so only keyboard arrival needs a marker. Same
   choice as the calc-map rows above. */
html.hsv-skin-next body .inner-calculator-content .calc-tabs .nav-tabs li a.nav-link:focus-visible,
html.hsv-skin-next body .inner-calculator-content .calc-tabs.original-tabs .nav-tabs li a.nav-link:focus-visible {
    box-shadow: var(--hsv-n-ring);
    outline: none;
}

/* Active. The kit bolds it (font-weight 700), which on a horizontal strip
   widens the tab and nudges every tab after it on each switch — React dodges
   that by rendering a hidden bold copy to reserve the width (see the
   EXTENSION note in web/src/ui/Tabs.tsx), a trick that needs markup this
   template does not have. `-webkit-text-stroke` thickens the glyphs without
   touching their metrics, so nothing moves. `font-weight` is the fallback
   where text-stroke is unsupported: a strip that shifts is still better than
   an active tab that does not read as active. */
html.hsv-skin-next body .inner-calculator-content .calc-tabs .nav-tabs li.active > a.nav-link,
html.hsv-skin-next body .inner-calculator-content .calc-tabs.original-tabs .nav-tabs li.active > a.nav-link {
    background-color: transparent;
    border-bottom-color: var(--hsv-n-navy);
    color: var(--hsv-n-navy);
    -webkit-text-stroke: .4px currentColor;
}

@supports not (-webkit-text-stroke: 1px currentColor) {
    html.hsv-skin-next body .inner-calculator-content .calc-tabs .nav-tabs li.active > a.nav-link,
    html.hsv-skin-next body .inner-calculator-content .calc-tabs.original-tabs .nav-tabs li.active > a.nav-link {
        font-weight: 700;
    }
}

/* ── Tab strip HEIGHT LOCKSTEP ────────────────────────────────────────────
   REQUIRED, not cosmetic. `.calc-tabs` is `overflow-y:hidden` and its
   `.tab-content` height is a HAND-MEASURED subtraction from the frame, not a
   layout: calculators.css:380 `calc(100% - 100px)`, :1708 `calc(100% - 50px)`
   for 1219, :1712 `calc(100% - 110px)` for 6111 (:391/:395 budget ורקות the
   same way, and are left alone — see the note at the end of this block). Each
   budget is (top-10 margin + strip height + slack) measured against the OLD
   strip, which was 7px of padding around a font those media queries kept
   resizing — so it measured 31px at 0.7em, 33px at 0.8em, 37px at the
   unshrunk 16px. The strip above is a flat 42px (10+10 padding, 14px text,
   2px underline, 1px hairline, less the li's -1px). Leave the budgets alone
   and the bottom of every tabbed calculator is clipped, with no scrollbar to
   reveal it.

   11px is the WORST case of that range (42 - 31, the narrow 0.7em step).
   Over-subtracting is the safe direction: the surplus on a wide viewport is
   a few px of unused space above the frame's own padding, while
   under-subtracting hides content outright.

   One variable, in one place, if the padding above ever moves. */
html.hsv-skin-next {
    --hsv-n-tab-grow: 11px;
}

html.hsv-skin-next body .inner-calculator-content .calc-tabs.original-tabs .tab-content {
    height: calc(100% - 100px - var(--hsv-n-tab-grow));
}
html.hsv-skin-next body.calculator-calcDocument1219-page .inner-calculator-content .calc-tabs.original-tabs .tab-content {
    height: calc(100% - 50px - var(--hsv-n-tab-grow));
}
html.hsv-skin-next body.calculator-calcDocument6111-page .inner-calculator-content .calc-tabs.original-tabs .tab-content,
html.hsv-skin-next body.calculator-calcDocument6111Accountant-page .inner-calculator-content .calc-tabs.original-tabs .tab-content {
    height: calc(100% - 110px - var(--hsv-n-tab-grow));
}
/* ורקות is NOT here, though calculators.css:391/:395 budget it the same
   way. Its tabset (dueDatesManagement.html:98) sits in .sentdoc-layout, not
   inside a .calc-tabs, so no rule above matches it and its strip keeps its
   legacy height — subtracting growth it never had would open 11px of dead
   space under a grid that is already tight. The .original-tabs .orkot rule
   next to it is dead either way: no view puts an .orkot inside
   .calc-tabs.original-tabs. */

/* ── The title strip (`.calculator-header`) ────────────────────────────────
   Restyled to the kit's `ProgramHeader` title row
   (heshev-design-system/ui_kits/heshev-financial/UI.jsx:239-273, CSS at
   styles.css:1703-1716): h1 26px/800/navy, the saved-report meta line
   13px/500/--fg-3. `.frame-top` — the icon-tool strip and breadcrumb trail
   above this — is NOT restyled; that attempt was reverted, so this section
   is typography only, scoped to `.calculator-header` and nothing above it.

   Typography only for what remains too. `.calculator-header` is deliberately
   NOT made a flex container: its three children are floated (.header-text
   right, .calc-button and .report-status-wrapper left — calculators.css:232,
   :289, :294), and in an LTR flex row the title would land on the wrong side
   while `row-reverse` would swap the other two against each other. The
   floats already produce the kit's layout; only the type is wrong. */

html.hsv-skin-next body .calculator-box .calculator-header .header-text .calc-title h1 {
    /* (0,5,3). The bar to clear is calculators.css:82's
       `body … .calc-title.calc-title-long h1` (0,4,2); also over :42's 26px
       @1350 and :256's 28px long-title rule (0,4,1), and mobile.css:110
       (0,2,2). print.css:200 carries !important and correctly keeps its own
       size — the print sheet is not this design.

       `.calc-title` matches both variants, since `calc-title-long` is an
       additional class on the same element (ng-class,
       calculatorFrame.html:431). So short and long titles unify at the kit's
       26px instead of legacy's 28/26/22 spread. */
    color: var(--hsv-n-navy);
    font-size: 26px;
    font-weight: 800;
    line-height: 1.15;
}

/* The saved-report name beside the title is the kit's `.pw-title-meta`
   (styles.css:1715): 13px/500/--fg-3. (0,6,3) vs calculators.css:251 (0,4,1).
   Colour and type only — the padding/margin that positions it is legacy's and
   stays, per this file's standing rule about the box model. */
html.hsv-skin-next body .calculator-box .calculator-header .header-text .calc-title .report-name {
    color: var(--hsv-n-fg-3);
    font-size: 13px;
    font-weight: 500;
}

/* The category glyph goes: the kit's title row has no icon, and at 70px wide
   it is the single biggest piece of legacy chrome left on the strip. The
   width reclaim on the next rule is REQUIRED, not optional —
   calculators.css:238 budgets `.calc-title` at `calc(100% - 75px)` for
   exactly this glyph, so hiding it alone would leave 75px of dead space at
   the title's start. */
html.hsv-skin-next body .calculator-box .calculator-header .header-text .icon {
    display: none;
}
html.hsv-skin-next body .calculator-box .calculator-header .header-text .calc-title {
    width: 100%;
}

/* The narrow steps, restated. Specificity alone would let the 26px above win
   everywhere, but those legacy steps exist for a reason: calculators.css:78
   and :38 shrink `.header-text` to `calc(100% - 125px)` while `.calc-title`
   is `white-space:nowrap; overflow:hidden` (:240-241), so a pinned 26px would
   silently truncate a long Hebrew title rather than reflow it. Same two
   breakpoints and the same two sizes legacy already chose. */
@media (max-width: 768px) {
    html.hsv-skin-next body .calculator-box .calculator-header .header-text .calc-title.calc-title-long h1 {
        font-size: 22px;
    }
}
@media (max-width: 736px) {
    html.hsv-skin-next body .calculator-box .calculator-header .header-text .calc-title h1 {
        font-size: 20px;
    }
}

/* NOT here, on purpose: the calculate button. #calc-btn carries
   `calc-btn btn-primary btn-fixed`, and the Buttons section above (line ~625)
   already paints every .btn-primary with --hsv-n-sky and --hsv-n-r-btn —
   which IS the kit's `sky` variant, the same one ProgramHeader gives its
   action. Restating it here would duplicate a live rule and risk re-opening
   the padding regression nextLegacyTheme.spec.ts:482 exists to catch. */
