/* Fine tuning of generated screens.
   Colour and size values come from tokens.css and are not repeated here. */

/* This file DEFINES no size/colour other than the tokens.
   The three rules below were left over from before the tokens; they were bound. */

/* ------------------------------------------------------------
   BASE TYPE — BODY AND INPUTS

   Two leaks were measured and both have the same cause: the rule
   writing the type was bound to the SHELL, so outside the shell and the
   browser's own defaults were left exposed.

   1. Radzen's body rule is `:root:has(.rz-layout) body`. WITHOUT the
      shell it never matches — on the `/giris`, `/kurulum` and `/sorun`
      screens the body was measured: 16px **Times New Roman**. So the
      login screen was not drawn in the application's font.

   2. Inputs do NOT INHERIT the font — a browser rule, not Radzen's.
      Radzen writes `font-family: inherit` on inputs with a class, but a
      classless `<input>` (lookup search box, grid filter) stays at the
      browser's default. Measured: inside the shell 44 inputs were
      **Arial**, everything else Geist.

   The base rule uses an element selector (0,0,1): every rule writing a
   class already beats it, so no component's look changes — only those
   writing nothing fall back to the token. */
body {
    font-family: var(--font-ui);
    font-size: var(--fs-body);
}

input,
select,
textarea {
    font: inherit;
    font-size: var(--fs-table);
}

.rax-required {
    color: var(--c-neg);
    margin-inline-start: 2px;
    font-weight: var(--fw-medium);
}

.rax-field-note {
    color: var(--c-ink-3);
    font-size: var(--fs-caption);
    margin-block-start: 1px;
}

.rax-field-error {
    color: var(--c-neg);
    font-size: var(--fs-caption);
    margin-block-start: 1px;
    line-height: var(--lh-tight);
}

/* ============================================================
   DENSITY — binds tokens.css to Radzen

   tokens.css had written the density system (--row-h, --cell-px,
   --fs-table + three tiers) but it was applied nowhere.

   WHAT I MISSED ON THE FIRST TRY: Radzen defines these variables ON THE
   GRID ITSELF —

       .rz-data-grid { --rz-grid-cell-padding: 0 1rem }

   An element's own declaration is stronger than what it inherits from
   an ancestor. So writing on `.rax-shell` did nothing. The variables
   must be overridden ON the grid element.

   Selector specificity: .rax-shell .rz-data-grid (0,2,0) >
   .rz-data-grid (0,1,0) and equal to .rz-data-grid.rz-density-compact
   (0,2,0) — rax.css wins because it loads last.
   ============================================================ */

/*  THE DROPDOWN TABLE'S GRID IS HERE TOO.

    In lookup table mode the opened panel is moved to `body`, so it is
    NOT under `.rax-shell` — this block did not reach it. Measured: while
    a list row was 26px/12px, the dropdown table's row came out 34px/13px.
    Two surfaces showing the same data must not diverge in size; the very
    decision made in K-076 for the dropdown list's row, this time in grid
    form.

    The selector goes through the panel's class: a grid inside
    `.rz-dropdown-panel` can only be this one. */
.rax-shell .rz-data-grid,
.rax-shell .rz-datatable,
.rz-dropdown-panel .rz-data-grid {
    --rz-grid-cell-padding:        0 var(--cell-px);
    --rz-grid-cell-font-size:      var(--fs-table);
    --rz-grid-cell-line-height:    var(--row-h);

    --rz-grid-header-padding:      0 var(--cell-px);
    --rz-grid-header-cell-padding: 0;
    --rz-grid-header-font-size:    var(--fs-caption);
    --rz-grid-header-line-height:  var(--header-h);

    --rz-grid-filter-padding:      0 var(--cell-px);
    --rz-grid-filter-font-size:    var(--fs-caption);
}

/*  Number columns.

    The rule here was DEAD: it targeted the `.rz-text-align-right` class
    but Radzen does not put TextAlign on the cell as a class — the cells'
    className is empty. So tabular figures were never applied (K-051).

    The decision was gathered in the `.rax-num` class in tokens.css;
    DynamicList wraps the cell with that class. One place, its consumer
    verified. */
.rax-shell .rz-data-grid td .rax-num {
    display: block;
}

/*  THE HEADER SIZE IS NOT BOUND HERE — see shell.css "GRID".

    Radzen's `--rz-grid-header-font-size` variable is not consumed on
    `th`: the block above defines it but the header still came out 13px,
    i.e. the same size as the data. It must be written directly on `th`
    and the grid's look is shell.css's job. */

/*  Inputs: the property directly instead of guessing a variable name.
    A form row must not take twice the room of a grid row.

    THE FONT SIZE LEFT THIS PLACE. This list counted five selectors and
    the count was incomplete: the numeric box's real class is
    `rz-numeric-input`, the date box's `rz-inputtext` — neither was in the
    list and both stayed at Radzen's own size (measured: 13px next to 12px
    boxes). The size's only author is now the `--rz-input-font-size`
    bridge in tokens.css; since the variable is inherited there is no need
    to count classes. */
.rax-shell .rz-textbox,
.rax-shell .rz-dropdown,
.rax-shell .rz-datepicker,
.rax-shell .rz-numeric .rz-spinner-input,
.rax-shell .rz-spinner-input {
    min-height: var(--row-h);
}

/*  The number INPUT is tabular too (K-051).

    The display side was solved with `.rax-num` but inputs were left
    out: on invoice lines quantity and amount are edited one under the
    other and with proportional digits none of them line up. Same token,
    second consumer.

    ALIGNMENT IS HERE NOW TOO: `--num-align` was once only a display
    decision and was left with "right-aligning the input affects the
    form's layout, it is a separate decision". That decision was made — a
    number is a number, right-aligned in a form as in a grid. With
    quantity and amount fields stacked, left-aligned digits broke the
    digit alignment.

    The class name is `rz-numeric-input`: the old rule targeted
    `rz-spinner-input` and never matched (found with a DOM dump). Both
    were kept — if the version changes the rule must not die silently. */
.rax-shell .rz-numeric .rz-numeric-input,
.rax-shell .rz-numeric .rz-spinner-input,
.rax-shell .rz-spinner-input {
    text-align: var(--num-align);
    font-variant-numeric: var(--num-variant);
}

/* Button: height the same as a row, horizontal space from the token.
   Radzen's default is 2.25rem height + 1rem horizontal padding — in a
   compact command strip six buttons eat half the screen. */
.rax-shell .rz-button {
    min-height: var(--row-h);
    height: var(--row-h);
    font-size: var(--fs-table);
    padding-block: 0;
    padding-inline: var(--btn-px);
    line-height: 1;
    letter-spacing: 0;
}

/*  An icon button stays square, it does not take as much room as text.

    CENTRING IS WRITTEN EXPLICITLY: the inner `.rz-button-box` centres
    inside itself but the box itself sat on the button's left — measured,
    on a 26px button there was 1px to the icon's left and 10px to its
    right. Centring a box's content is not the same as centring the box. */
.rax-shell .rz-button.rz-button-icon-only {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding-inline: 0;
    width: var(--row-h);
    min-width: var(--row-h);
}

.rax-shell .rz-button.rz-button-icon-only > .rz-button-box {
    flex: 1 1 auto;
    justify-content: center;
}

.rax-shell .rz-button .rzi,
.rax-shell .rz-button .rz-button-box > i {
    font-size: calc(var(--fs-table) + 3px);
    width: auto;
    height: auto;
    line-height: 1;
}

.rax-shell .rz-button .rz-button-box {
    gap: var(--sp-2);
    line-height: 1;
}

/* Fieldset legend: 1rem padding is a waste for a 15px title. */
.rax-shell .rz-fieldset-legend,
.rax-shell .rz-fieldset > legend {
    padding: 0 var(--sp-2);
    font-size: var(--fs-section);
    line-height: var(--lh-tight);
}

.rax-shell .rz-fieldset {
    margin-block: 0;
}

/* Menu: row height and padding follow the density too. */
.rax-shell .rz-navigation-item-link,
.rax-shell .rz-panel-menu .rz-navigation-item-link {
    padding-block: 0;
    padding-inline: var(--cell-px);
    min-height: var(--row-h);
    font-size: var(--fs-table);
}

.rax-shell .rz-header {
    min-height: calc(var(--row-h) + var(--sp-3));
}

.rax-note { padding: var(--pad); }

/* Pager. The class is `.rz-pager` — there is no such thing as
   `.rz-paginator`, the old rule here had never matched. */
/*  The pager is THE SAME HEIGHT AND LANGUAGE AS THE COLUMN HEADER.

    The previous decision matched it to the TOP COMMAND STRIP (`--bar-h`,
    38px). Measured: header 25px, pager 38px — the grid sat between two
    frames of different weight and the bottom looked heavy.

    The right pair is the header: both are the grid's own frame, one
    opening, one closing. The command strip is the card's frame and has
    an input inside — it stays at `--bar-h`, it cannot shrink.

    The line colour is the same as the header's too (`--c-line-2`,
    emphasised divider); it used to be `--c-line` and the bottom edge came
    out fainter than the top. */
/*  +1px BORDER ALLOWANCE: the header `th` height is `--header-h` and its
    border is ADDED TO IT (25px). The pager is `border-box` so its border
    counts inside; 1px is added to match. Written without measuring, a 1px
    difference would have remained. */
.rax-shell .rz-pager {
    box-sizing: border-box;
    height: calc(var(--header-h) + 1px);
    min-height: calc(var(--header-h) + 1px);
    align-items: center;
    padding-block: 0;
    padding-inline: var(--cell-px);
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    letter-spacing: .06em;
    background: var(--c-surface-2);
    border-top: 1px solid var(--c-line-2);
    color: var(--c-ink-2);
}

/*  THE PADDING IS RESET, otherwise the height does not hold.

    Measured: page buttons came out 39px — even though
    `height: var(--row-h)` (26px) was written. The cause is Radzen's
    rem-based 9.75px padding; the padding is added to `height` and the
    button inflated the strip. If the strip's height comes from the
    button, the button's size must come from one place. */
.rax-shell .rz-pager .rz-pager-element {
    box-sizing: border-box;
    min-width: calc(var(--header-h) - 4px);
    width: auto;
    height: calc(var(--header-h) - 4px);
    min-height: 0;
    padding: 0 var(--sp-2);
    line-height: 1;
    border-radius: var(--r-control);
    color: var(--c-ink-2);
}

.rax-shell .rz-pager .rz-pager-page.rz-state-active {
    background: var(--c-accent);
    color: var(--c-on-accent);
}

/* ------------------------------------------------------------
   PAGER ADD-ONS — go to page, page size

   The strip has three zones: arrows and page buttons on the left,
   "Sayfa __ / N" in the MIDDLE, "__ satır · N kayıt" on the RIGHT. The
   box in the middle does not replace the arrows but complements them —
   in a forty-page list nobody presses "next" thirty times.
   ------------------------------------------------------------ */

/*  `order` CUTS THE DEPENDENCY ON ORDER.

    Wherever Radzen draws the summary in the strip, the add-ons go to the
    end. Relying on order would be a silent dependency on Radzen's markup
    — a version later the add-ons would drop to the left of the arrows and
    nobody would look for why. */
.rax-shell .rz-pager .rz-pager-summary {
    order: 9;
    flex: 1 1 auto;
    min-width: 0;
}

.rax-pagerx {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    /* Lean on the right end: this zone eats all the space between it and
       the button group on the left. */
    justify-content: flex-end;
}

.rax-pagerx-goto,
.rax-pagerx-size {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    white-space: nowrap;
}

/*  MIDDLE: automatic margins from both sides. `justify-content` alone
    could not centre it — the block on the right is on the same line and
    its width changes with the number of records. */
.rax-pagerx-goto {
    margin-inline: auto;
}

/*  The box DOES NOT INFLATE THE STRIP. Its height comes from the same
    token as a page button; if Radzen's rem-based input padding reached
    here the pager would grow again from the 25px measured in K-065. */
.rax-pagerx-input {
    box-sizing: border-box;
    width: 4.5em;
    height: calc(var(--header-h) - 4px);
    min-height: 0;
    padding: 0 var(--sp-2);
    border: 1px solid var(--c-line-2);
    border-radius: var(--r-control);
    background: var(--c-surface);
    color: var(--c-ink);
    font: inherit;
    font-variant-numeric: var(--num-variant);
    letter-spacing: 0;
    text-align: center;
}

/*  ONE FRAME — focus changes the COLOUR, it does NOT ADD a ring.

    The box's own 1px border turned to the accent AND `--focus-ring` was
    put on top. The token itself is a double ring (2px light + 3px
    accent) and the ring sits OUTSIDE the border, with a light gap
    between: the result is two accent lines with a strip between — the
    box looks double framed.

    The rule is written TWICE in this repository (the focus note of
    `.rax-field` and that of `.rax-search-field`) but it was not applied
    in five of the bordered controls. The ring is the tool of elements
    WITHOUT a frame: button, tab, menu row. In a box with a border the
    mark is already there — changing its colour is enough.

    `box-shadow: none` MUST BE WRITTEN, removing the ring from here is NOT
    ENOUGH. Measured: after the declaration was removed the ring was still
    drawn — the global rule in tokens.css
    (`:where(button, input, select, [tabindex]):focus-visible`) puts the
    same ring on every input and our own rule can only silence it by
    OVERWRITING it. The note of `.rax-search-field` had already listed
    this third source. */
.rax-pagerx-input:focus {
    border-color: var(--c-accent);
    box-shadow: none;
    outline: none;
}

/*  The number arrows were REMOVED.

    `type="number"` stays for arrow-key stepping and the numeric keyboard
    on mobile; the visual arrows eat half the box in a 24px strip and
    come out too small to click. */
.rax-pagerx-input {
    appearance: textfield;
    -moz-appearance: textfield;
}

.rax-pagerx-input::-webkit-outer-spin-button,
.rax-pagerx-input::-webkit-inner-spin-button {
    appearance: none;
    -webkit-appearance: none;
    margin: 0;
}

/* The labels are in the strip's own tone: the box is data, the word next
   to it is not. */
.rax-pagerx-label {
    color: var(--c-ink-3);
    font-weight: var(--fw-normal);
    letter-spacing: 0;
}

/* ============================================================
   WORK AREA — TABS

   The strip itself (nav background/border, li, button padding, panel
   padding) is NOT DEFINED here — shell.css's "minimal tab" block carries
   the same selectors and since it loads LATER (App.razor: tokens → rax →
   shell) it always wins at equal specificity. Besides, the old rule
   targeted `li a`; Radzen 11 draws a `<button>`, so it never matched
   anyway (shell.css's own note). It was removed for being dead code for
   two reasons — keeping it would raise the question "which file wins" in
   the future.

   The tab's CONTENT (title, close cross) is still here — those are not
   redefined in shell.css.
   ============================================================ */

.rax-tab-title {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    max-width: 18ch;
}

.rax-tab-title > span:nth-child(2) {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Close cross: part of the tab title, not a separate button — a separate
   button would grow the tab's height. */
.rax-tab-close {
    font-family: 'Material Symbols', 'Material Icons';
    /* A fixed 15px stayed large on a 12px tab in the compact tier. */
    font-size: calc(var(--fs-table) + 2px);
    line-height: 1;
    opacity: 0.45;
    cursor: pointer;
    border-radius: var(--r-control);
}

.rax-tab-close:hover {
    opacity: 1;
    background: var(--c-line);
}

/*  The padding is NOT HERE but in `.rax-form-body`: the command strip must
    stick to the card's edge (like the list's strip), only the scrolling
    body starts further in. With padding on the card the strip would move
    in too and the strips of the two screens would be misaligned.

    `max-width: 1100px` REMOVED. Its aim was keeping the line length
    readable but the cost was a huge gap on the right on a wide screen —
    besides, the record screen is not plain text but fields set in a
    grid: when it widens the lines do not get longer, the fields sit more
    comfortably side by side. What really protects readability is the
    field's own width (`Width`), not the card's limit. */

.rax-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-4);
    padding: var(--sp-7);
    color: var(--c-ink-3);
}

.rax-empty-icon {
    font-family: 'Material Symbols', 'Material Icons';
    font-size: 40px;
    opacity: 0.35;
}

/* ============================================================
   FORM — MULTI-COLUMN

   The label-left / field-right layout spent one row per field: a
   nine-field customer form overflowed the screen. Label on top, fields
   in a grid — the same form drops to a third of the height.
   ============================================================ */

/*  SECTION TITLE: not a box but a divider.

    Every field already carries its own frame. If the section also drew
    a full frame the form would split into nested boxes and every edge
    would read as equally important. The corporate form language here is
    calmer: a title, then a thin divider line. */
/*  THE SECTION TITLE DOES NOT COMPETE WITH THE FIELDS.

    It was 15px; field labels are 11px. That jump made the title the
    noisiest element in the form — yet the title is not something to
    read but a sign saying where to look. Small + CAPS + letter spacing:
    less ink on the same line, more hierarchy.

    The form was not made up, it was already in the repository: the
    header cell of the consultant table (`.rax-overlay-table th`) is this
    word for word. No two separate "group label" languages in two places. */
/*  A MARK BEFORE THE TITLE, A LONG LINE AFTER IT (K-235).

    Three tries were made and the decision was taken on screen: a leading
    line (K-234) was not liked, a short trailing line did not hold either.
    What remains is this — a small mark in front, a thin line behind
    stretching to the end of the row.

    A MARK, NOT A LINE: when the leading piece was a line the title looked
    squeezed and centred between two lines. A small square does the same
    job — «a new section starts here» — but does not break the title's
    alignment.

    Its size is tied to the text (`0.45em`): when the density tier grows
    the text the mark grows too, no separate token is needed. */
.rax-form .rz-fieldset > legend,
.rax-form .rz-fieldset-legend,
.rax-config-title {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    width: 100%;
    margin: 0 0 var(--sp-3);
    padding: 0;

    /*  ONE TONE DARKER (K-234): `--c-ink-3` is as faint as secondary text
        — the title did not stand apart from the field label next to it.
        `--c-ink-2` is still below the ink, so the title makes no noise but
        reads as the section's name. */
    color: var(--c-ink-2);
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    text-transform: uppercase;
    letter-spacing: .04em;
    line-height: var(--lh-tight);
}

/*  THE MARK: A SMALL SQUARE IN THE ACCENT COLOUR.

    At one point it was turned into a thin vertical bar and VANISHED on
    screen — a faint 2px bar reads not as a mark but as the line's
    continuation. The mark's job is to be seen: it must tell where the
    section starts without the eye scanning.

    Its size is tied to the text (`0.45em`, ~5px in the compact tier):
    when the density tier grows the text the mark grows too, no separate
    token is needed. */
.rax-form .rz-fieldset > legend::before,
.rax-form .rz-fieldset-legend::before,
.rax-config-title::before {
    content: "";
    flex: 0 0 auto;
    inline-size: 0.45em;
    block-size: 0.45em;
    border-radius: 1px;
    background: var(--c-accent);
}

/*  THE DIVIDER LINE: 1PX AND ONE STEP CLEARER.

    Three tones were tried — 16% (too much), 6% + 0.5px hairline
    (vanishes), 10% (kept). `--c-field-line` is the same token as the
    field's frame, no new value was made.

    THE 0.5PX OPTION WAS DROPPED and the owner decided: «the thinnest
    should be 1px». A hairline is possible on a dense display but the
    result varied with the screen's density — the same interface drawn two
    ways on two machines. A fixed 1px is the predictable one. */
.rax-form .rz-fieldset > legend::after,
.rax-form .rz-fieldset-legend::after,
.rax-config-title::after {
    content: "";
    flex: 1 1 auto;
    border-block-start: 1px solid var(--c-field-line);
}

.rax-form .rz-fieldset {
    margin: 0 0 var(--sp-4);
    padding: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
}

.rax-form .rz-fieldset:last-child {
    margin-block-end: 0;
}

.rax-form .rz-fieldset-content {
    padding: 0;
}

/*  THE SPACING IS THE SAME ON BOTH AXES.

    `row-gap` was written, `column-gap` was not: Radzen's `--rz-gap` (2px
    in the compact tier) stayed on the horizontal. Measured —
    `gap: 6px 2px`. Between two field frames side by side there was 2px,
    between stacked ones 6px.

    The reason for raising `--form-gap` for rows ("when two fields' frames
    sit 2px apart the eye cannot tell which label belongs to which box",
    tokens.css) describes the HORIZONTAL neighbour word for word — the
    rule was written but not applied on the axis that created the need.

    THE FIX CANNOT BE MADE WITH `gap`, IT IS MADE WITH THE VARIABLE.
    Measured: the column width is `calc(25% - 1.5px)` — so Radzen derives
    the column's size from `--rz-gap`. Writing only `gap`, the columns
    would still shrink by 1.5px, three gaps would be 6px and the fourth
    field would drop to the next row. Feeding the variable fixes both at
    once: `calc(25% - 4.5px) * 4 + 6px * 3 = 100%`. */
.rax-form .rz-fieldset-content > .rz-row {
    --rz-gap:     var(--form-gap);
    --rz-row-gap: var(--form-gap);
}

/* ------------------------------------------------------------
   FIELD FRAME — the label inside the border

   fieldset/legend: the browser itself cuts the room the legend takes out
   of the border. No fake background or JS measurement.

   The frame IS NOW THE FIELD ITSELF: the Radzen input inside is
   borderless and transparent, otherwise two nested frames would show.
   ------------------------------------------------------------ */

/*  THE HORIZONTAL PADDING MOVED IN (2→8px), vertical stays zero.

    At 2px the text stuck to the border. This single value shifts BOTH
    the label AND the value — since the legend takes back its own
    horizontal padding with a negative margin, both keep starting at the
    same left edge. This is how to move in without breaking alignment.

    Vertically it is still zero: the space there comes from the input's
    own height and that is what gets multiplied by the number of fields. */
/*  THE FIELD HAS NO BACKGROUND, ONLY A FRAME.

    When the screen's background moved to the canvas (K-087) the fields
    turned into white boxes: the card canvas, every field inside white. A
    form with fifteen fields means fifteen white rectangles — the eye
    reads them as objects, not data.

    The background was removed, THE FRAME STAYS. What made a field a
    field was already its border and label; colour was a third and
    unnecessary mark.

    THE FRAME IS THE EMPHASISED LINE (`--c-line-2`), not the hairline.
    With background and fill gone, this line is the ONLY thing left
    saying where the field starts and ends; if its load grew its weight
    must grow too. Measured: 1.40 contrast with the hairline, 1.75 with
    the emphasised one. */
.rax-field {
    min-width: 0;
    margin: 0;
    padding: 0 var(--sp-3) 0;

    /*  The frame is NOT THE SAME WEIGHT as the grid line (see tokens.css).
        In a nine-field form nine boxes became the thing consuming the
        most ink on screen; what is read is the values, not the frames. */
    border: 1px solid var(--c-field-line);
    border-radius: var(--r-control);
    background: transparent;
    transition: border-color var(--motion) linear;
}

/* ------------------------------------------------------------
   THE INPUT INSIDE PAINTS NOTHING

   The Radzen input paints its own border, background and shadow from the
   `--rz-input-*` variables. These were attempted to be overridden as
   PROPERTIES but the `:hover` rule's selector
   (`.rz-textbox:not(:disabled):not(.rz-state-disabled):hover`) is more
   specific than `.rax-field .rz-textbox` — on hover Radzen won and
   spilled outside the frame.

   The right way is feeding the variable (the same lesson as
   K-032/K-036): the variable is INHERITED, so once defined here the
   selector specificity argument ends.

   There is ONE visual boundary: the field frame or the line grid's own
   lines. Both consumers read the same list — written a second time, one
   would diverge one day.

   THE VARIABLES ARE WRITTEN ON THE ELEMENT ITSELF, not on an ancestor:
   Radzen defines them on the input and the element's own declaration
   beats inheritance. Tried on the ancestor, measured, did not hold —
   the input still showed Radzen's value.
   ------------------------------------------------------------ */
.rax-field .rz-textbox,
.rax-field .rz-dropdown,
.rax-field .rz-numeric,
.rax-field .rz-datepicker,
.rax-field .rz-spinner,
.rax-field .rz-inputtext,
.rax-lines .rz-textbox,
.rax-lines .rz-dropdown,
.rax-lines .rz-numeric,
.rax-lines .rz-datepicker,
.rax-lines .rz-spinner,
.rax-lines .rz-inputtext {
    --rz-input-shadow:                   none;
    --rz-input-hover-shadow:             none;
    --rz-input-focus-shadow:             none;
    --rz-input-disabled-shadow:          none;

    --rz-input-border:                   none;
    --rz-input-hover-border:             none;
    --rz-input-focus-border:             none;
    --rz-input-disabled-border:          none;

    --rz-input-border-block-end:         none;
    --rz-input-hover-border-block-end:   none;
    --rz-input-focus-border-block-end:   none;
    --rz-input-disabled-border-block-end: none;

    --rz-input-background-color:         transparent;
    --rz-input-hover-background-color:   transparent;
    --rz-input-focus-background-color:   transparent;
    --rz-input-disabled-background-color: transparent;

    --rz-input-focus-outline:            none;
    --rz-input-focus-outline-offset:     0;
    --rz-input-border-radius:            0;
    --rz-input-padding-inline:           0;

    /*  THE REAL SOURCE OF THE HEIGHT.

        Measured: `min-height` had dropped to 17px but the input stayed
        32.5px. The cause is Radzen writing `height: var(--rz-input-height)`
        — `height` beats `min-height`. So the size was set not by our rule
        but by that variable, and trimming the padding changed nothing.

        Feeding the variable is the right way (K-032/K-036's lesson): from
        one place the text box, dropdown, date picker and number field all
        come to the same size. */
    --rz-input-padding-block:            0;

    --rz-dropdown-open-border:           none;
    --rz-dropdown-open-background-color: transparent;
}

/* Hover: only the frame darkens. No second highlight inside the box — the
   field is already one object.

   As the resting weight dropped, the target dropped too: it used to go
   up to 26%, now 16%. The jump ratio is kept (about 1.6 times) but the
   peak value no longer overwhelms the rest of the form. */
.rax-field:hover:not(:focus-within) {
    border-color: var(--c-line);
}

/*  THE LABEL AND THE VALUE start at THE SAME LEFT EDGE.

    At one point the label was shifted 2px right; measured, the label
    started at 212 and the value at 210 and the eye reads those 2px as
    misalignment. The legend's own horizontal padding (needed for the
    notch) is taken back with a negative margin. */
.rax-field > legend {
    padding-inline: var(--sp-1);
    margin-inline-start: calc(-1 * var(--sp-1));
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    color: var(--c-ink-2);
    line-height: 1;
    white-space: nowrap;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}

/*  FOCUS: THE FRAME ITSELF, NOT A RING AROUND IT.

    `--focus-ring` was put here too (2px light + 3px accent) and a second
    line appeared OUTSIDE the field's own border, with a gap between — the
    box looked double framed.

    The field already carries its own frame; on focus that frame's COLOUR
    changes and the label turns to the accent. Two marks are enough, a
    third is noise. A ring is the right tool for elements without a frame
    (button, tab, menu) — there the general rule in tokens.css keeps
    working.

    NO THICKENING EITHER. At one point the border was thickened with an
    `inset` shadow, but `box-shadow` does not know the fieldset's LEGEND
    NOTCH: the border is cut where the legend is, the shadow is not, and a
    thin line ran behind the label — "Ad soyad" looked struck through.

    So there is no clean way to thicken the frame in this box: if the
    border itself thickens the layout shifts 1px, if a shadow is used the
    label gets struck. One mark remains and it is enough: COLOUR. */
.rax-field:focus-within {
    border-color: var(--c-accent);
}

.rax-field:focus-within > legend { color: var(--c-accent); }

.rax-field-bad { border-color: var(--c-neg); }
.rax-field-bad > legend { color: var(--c-neg); }

/*  A READ-ONLY FIELD IS MARKED BY THE LINE, NOT THE BACKGROUND.

    First it was set apart by a fill (one notch darker than the
    background). The fill changed direction twice — "darker" on a white
    background, "lighter" on the canvas — and each time it had to be
    retuned. The lasting fix is dropping the fill: the field is now
    TRANSPARENT like its editable sibling.

    THE MARK IS THE LINE'S TONE. For one round a DASHED LINE was tried and
    dropped: it looked sensible on paper, but 1px dashes around a 26px
    box give a jagged edge and make noise in a calm form.

    Instead one tone down in the same family: an editable field has the
    EMPHASISED line (`--c-line-2`, contrast 1.75), a read-only field the
    HAIRLINE (`--c-line`, 1.40). The difference is slight but systematic —
    the eye sees fifteen fields side by side in a form and groups the
    weakly lined ones.

    The label is in faint ink too (the rule above), so two marks work
    together: a weaker frame + a fainter label.

    THE VALUE IS NOT FAINT: it is what is read. The text colour stays full
    ink (the `-webkit-text-fill-color` rule below). */
.rax-field:has(:disabled),
.rax-field:has(.rz-state-disabled) {
    background: transparent;

    /* The tier was KEPT, both went down: writable field 10%, read-only
       6%. The difference stays in the same place proportionally. */
    border-color: var(--c-field-line-soft);
}

.rax-field:has(:disabled) > legend,
.rax-field:has(.rz-state-disabled) > legend {
    color: var(--c-ink-3);
}

/*  THE SELECTOR COVERS THE LINE GRID TOO.

    The rule was written only for `.rax-field` and the line grid was left
    out: in view mode the Stock column was in full ink (LookupEditor writes
    its own plain text) while Quantity, Unit price, VAT and Line
    description were drawn as disabled `<input>`s and took Radzen's
    `--rz-text-disabled-color`.

    Measured: #191A1F and #6B6B6D side by side on the same row — contrast
    17.37 against 5.32. Both are readable but the eye reads the difference
    as "these columns matter less"; yet all are data of the same document
    and exactly what the user came to read.

    This is the third repeat of K-105: in this file `.rax-field` and
    `.rax-lines` are written SIDE BY SIDE in six separate rules (input
    variables, number arrows, dropdown label, date trigger...) — the pair
    broke only here.

    Today disabled state in the grid comes ONLY from view mode
    (`LineEditor` reads one flag: `Disabled = Locked`), so there is no such
    case as "a disabled but editable column". Were there one, the mark
    would be carried by the FRAME and LABEL as in the fields, not the
    value's ink — the decision above holds there too. */
.rax-field :disabled,
.rax-field .rz-state-disabled,
.rax-field .rz-state-disabled .rz-dropdown-label,
.rax-field .rz-state-disabled .rz-inputtext,
.rax-lines :disabled,
.rax-lines .rz-state-disabled,
.rax-lines .rz-state-disabled .rz-dropdown-label,
.rax-lines .rz-state-disabled .rz-inputtext {
    color: var(--c-ink);
    opacity: 1;
    -webkit-text-fill-color: var(--c-ink);
}

/*  ONE ELEMENT CARRIES THE HEIGHT.

    The defect was this: `min-height` was given both to the wrapper
    (`.rz-dropdown`) and to the label inside it (`.rz-dropdown-label`).
    Added together the box doubled and the text stuck to the top — that
    was what left a huge gap under the "Cari" field on screen. With a
    single element in a plain text box the problem did not show; the
    inconsistency came from this asymmetry.

    Rule: the OUTER element gives the height and CENTRES its content
    VERTICALLY, the inner element only writes. */

/*  THE HEIGHT VARIABLE IS WRITTEN ON THE ELEMENT ITSELF.

    Measured: `--rz-input-height` written on `.rax-field` showed
    `calc(26px - 9px)` on the field but `2.5rem` on the INPUT — Radzen
    defines this variable on the input itself and the element's own
    declaration beats inheritance.

    This is exactly the twin of the trap written in tokens.css for the
    grid variables. The note there has now found its second consumer:
    "those defined on the element itself are not fed from an ancestor."

    Why the variable instead of `height`: Radzen writes
    `height: var(--rz-input-height)` and `height` beat our `min-height`.
    Fixing the place that gives the size is better than stacking one more
    rule on top. */
.rax-field .rz-textbox,
.rax-field .rz-dropdown,
.rax-field .rz-numeric,
.rax-field .rz-datepicker,
.rax-field .rz-spinner,
.rax-field .rz-inputtext {
    --rz-input-height: calc(var(--row-h) - 9px);
}

/* Outer: wrappers. */
.rax-field .rz-dropdown,
.rax-field .rz-numeric,
.rax-field .rz-datepicker,
.rax-field .rz-spinner {
    display: flex;
    align-items: center;
    width: 100%;
    border: none;
    background: transparent;
    box-shadow: none;
    min-height: calc(var(--row-h) - 9px);
    padding: 0;
}

/*  Outer: direct inputs (no wrapper).

    `display: block` IS REQUIRED. `<input>` is an inline element and
    leaves a descender gap below it from the line box. Measured: a text
    box field 32px, a dropdown field 29px — even though both carry the
    same 17px input. Since the wrappers were given `flex` the problem did
    not show there; this was the whole of the remaining inconsistency. */
.rax-field .rz-textbox {
    display: block;
    width: 100%;
    border: none;
    background: transparent;
    box-shadow: none;
    min-height: calc(var(--row-h) - 9px);
    padding: 0;
    line-height: var(--lh-tight);
}

/*  Inner: only writes, gives NO height.

    Radzen's vertical padding is rem based and it, not `min-height`,
    set the box's height — next to the trimmed 2px there sat a 14px
    padding. */
.rax-field .rz-dropdown .rz-dropdown-label,
.rax-field .rz-datepicker input,
.rax-field .rz-numeric .rz-numeric-input,
.rax-field .rz-numeric .rz-spinner-input,
.rax-field .rz-spinner-input,
.rax-field .rz-inputtext {
    flex: 1 1 auto;
    min-height: 0;
    padding: 0;
    line-height: var(--lh-tight);
}

/*  NUMBER ARROWS HIDDEN.

    Radzen's up/down buttons fall on a glyph with no counterpart in the
    icon font and show up in the cell as a lone "<" — even in read-only
    amount fields. In accounting quantities are entered with the keyboard,
    not arrows; the buttons are useless and clutter. */
.rax-field .rz-numeric-button,
.rax-lines .rz-numeric-button,
.rax-field .rz-spinner-up,
.rax-field .rz-spinner-down,
.rax-lines .rz-spinner-up,
.rax-lines .rz-spinner-down {
    display: none;
}

/*  THE DROPDOWN LABEL LEANS LEFT.

    Measured: the wrapper started at 210 and was 1055px wide but the label
    sat at 621 — i.e. in the middle.

    The cause is not a margin but an INVISIBLE SIBLING: the
    `.rz-helper-hidden-accessible` put there for screen readers is in the
    flow with `position: static` and takes 158px. When we made the wrapper
    `flex` it became a flex item too and pushed the label forward.

    It is taken out of the flow — an invisible helper should have no share
    in layout. It does not escape the screen reader either: it is not
    deleted, only left without size. */
.rax-field .rz-dropdown .rz-helper-hidden-accessible,
.rax-lines .rz-dropdown .rz-helper-hidden-accessible {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
}

/*  THE INVISIBLE HELPER'S CARET IS INVISIBLE TOO.

    Defect: after a selection a thin, vertical, unrelated line stayed in
    the MIDDLE of the box.

    Measured. The helper input is 1×0 pixels at x=464 — the box is
    302→628, so exactly its middle; matching the line in the screenshot
    one to one. After a selection Radzen gives FOCUS to it for keyboard
    support (`document.activeElement` verified) and the input's
    `caret-color` is the ink, font size 13px. So the box has zero height
    but the caret is drawn at text height and spills outside the 1px clip.

    The `clip-path` above is not enough: it hides the ELEMENT, while the
    browser's caret can stay outside the clip. The right way is putting
    out the caret.

    The element is NOT DELETED, only left unpainted. No cost: measured,
    the input is already `aria-hidden="true"`, `readonly` and
    `tabindex="-1"` — the screen reader never sees it, Radzen uses it only
    as a focus target for the keyboard. The focus ability stays.

    The sentence of the rule above holds here too: "an invisible helper
    should have no share in layout." Nor in painting. */
.rax-field .rz-helper-hidden-accessible input,
.rax-lines .rz-helper-hidden-accessible input,
.rz-lookup-panel .rz-helper-hidden-accessible input {
    caret-color: transparent;
    color: transparent;
    background: transparent;
}

/*  The width is IMPOSED, not left to `flex-grow`.

    After the invisible sibling was taken out of the flow the label was
    the only flex item and carries `flex: 1 1 auto` — it should normally
    fill its container. The measurement still showed 233px width and a
    position right in the middle. Instead of chasing the cause the width
    is given directly: `width: 100%` is both enough and indisputable in
    this box. */
/*  The label's BOX behaves like the input's too.

    Measured: the cells' boxes lined up but the dropdown's selected value
    sat a pixel or two higher. The cause is the type difference: the number
    is an `<input>` and the browser centres its text in its own box, while
    the dropdown's label is a `<div>` and its text sits roughly at the
    line height.

    With full height + vertical centring on the label too, both follow the
    same rule and the row flattens. */
.rax-field .rz-dropdown .rz-dropdown-label,
.rax-lines .rz-dropdown .rz-dropdown-label {
    display: flex;
    align-items: center;
    height: 100%;
    flex: 1 1 100%;
    width: 100%;
    margin-inline: 0;
    text-align: start;
}

/* Radzen puts its own focus shadow; the frame already shows it. */
.rax-field .rz-textbox:focus,
.rax-field .rz-dropdown.rz-state-focused,
.rax-field .rz-numeric .rz-numeric-input:focus,
.rax-field .rz-spinner-input:focus,
.rax-field .rz-datepicker input:focus {
    box-shadow: none;
    outline: none;
    border: none;
}

/*  NO SECOND FRAME ON HOVER.

    What was done above for focus had NOT been done for hover: Radzen puts
    its own border on the inner input with `--rz-input-hover-border` and a
    second frame appeared inside our fieldset frame. The 1-2 pixel gap
    between the two lines makes the field look shaky.

    The right way: the frame is ONE and outside; on hover no new line
    appears, the EXISTING line's colour darkens. */
.rax-field .rz-textbox:hover,
.rax-field .rz-dropdown:hover,
.rax-field .rz-numeric:hover,
.rax-field .rz-datepicker:hover,
.rax-field .rz-spinner:hover,
.rax-field .rz-form-field:hover .rz-form-field-content,
.rax-field .rz-form-field-content:hover {
    border: none;
    box-shadow: none;
}

/* The outer frame's hover colour is NOT HERE: it is in the
   `.rax-field:hover:not(:focus-within)` rule above and focus priority is
   resolved there. The decision was already written — the only thing
   missing was silencing the inner border. */

/*  THE CALENDAR BUTTON SITS AT THE FIELD'S RIGHT EDGE.

    Measured: the field's inner right edge is 1257, the dropdown's arrow at
    1256 (aligned), the calendar button at **1248** — 9px inside. When the
    controls of two side-by-side fields end at different places the
    column edge looks broken.

    Cause: Radzen places the button with
    `position: absolute; right: 0.625rem` (8.125px in the compact tier).
    The dropdown's arrow is an ordinary flex item, so it leans to the end
    by itself. The difference was here — not in the button's size or the
    field's padding.

    `right: 0` is enough; the positioning method is not changed. The
    input's right padding (2.5rem) is wider than the button, so the text
    does not go under the button.

    IT IS CENTRED VERTICALLY TOO — and the defect here was bigger than the
    horizontal one. Measured: Radzen gives the button a fixed `top: 8.5px`
    but the wrapper is only **17px** tall (the input's height) and the
    button 26px. Result: the button was 18px below the field's middle and
    OVERFLOWED THE BOTTOM EDGE BY 16px — hanging outside the box.

    `top: 50%` + a `-50%` translate seats the button at the wrapper's real
    middle; it stays in the middle even if the size changes. The
    horizontal translate was merged into the same `transform`: written as
    two separate rules the second would override the first (`transform` is
    one property). */
/*  CENTRING MUST LOSE TO NO RULE (K-167).

    The user reported the icon sitting on the box's BOTTOM EDGE and it was
    measured from the screenshot: the icon's centre at 95% of the box's
    height. In every measurement on my side 50% — so in their browser this
    rule was NOT APPLIED. Radzen's default (`top: 8.5px`, button 26px,
    wrapper 17px) produces exactly that image.

    Two things were done at once, because I could not see the cause from
    afar:

    1) SPECIFICITY WINS FOR SURE. Raised to (0,6,0) with `:is()`; the most
       specific rule Radzen writes for this element is (0,4,0).
       `!important` was NOT WRITTEN — it silences the next rule too and
       makes the cause invisible.

    2) VERTICAL CENTRING NO LONGER DEPENDS ON `transform`.
       `inset-block: 0` + `margin-block: auto` seats the absolutely
       positioned box at the wrapper's real middle. `transform` carries
       only the HORIZONTAL shift.

       Reason: `transform` is ONE property. Centring and shifting used to
       both be inside it; if Radzen ever wrote any `transform` on the
       button (press effect, icon rotation) centring would drop TOGETHER.
       Now even if it drops the icon stays in the middle, it would only
       move 8px in.

    LET THE OLD DEFECT STAY ON RECORD: Radzen gives the button a fixed
    `top: 8.5px` but the wrapper is 17px and the button 26px — the button
    ended up 18px below the field's middle and overflowing the bottom edge
    by 16px. */
:is(.rax-field, .rax-lines) :is(.rz-datepicker, .rz-form-field-content)
    :is(.rz-datepicker-trigger, .rz-timespanpicker-trigger),
.rax-field .rz-datepicker-trigger,
.rax-lines .rz-datepicker-trigger {
    right: 0;

    /*  Vertical centring: the box stretches from both ends and the `auto`
        margins share the spare room equally. The same result as
        `top: 50%` + translate, but independent of `transform`. */
    inset-block: 0;
    margin-block: auto;

    /*  THE HORIZONTAL SHIFT USES `margin`, NOT `transform` (K-168).

        The cause was measured: our press effect
        `.rax-shell .rz-button:not(.rz-state-disabled):active
         { transform: translateY(1px) }`
        with specificity (0,4,0) OVERRIDES this rule (0,3,0). `transform`
        is a single property — when pressed our `translateX(8px)` vanished
        and the icon jumped 8px to the LEFT.

        The user's description matched the measurement one to one: first
        "down left" (vertical was in the transform too, before K-167),
        after K-167 only "left".

        The layout no longer touches transform at all: `margin` pushes the
        absolutely positioned box out from its `right` anchor. The press
        effect does its own job too — 1px down, no side effect. */
    margin-inline-end: calc(-1 * var(--sp-3));

    /*  RADZEN'S OWN TRANSLATE IS SILENCED (K-168).

        Radzen gives the button `transform: translateY(-50%)` — to centre
        together with `top: 50%`. Since our centring is now done with
        margins, that translate is left OVER and pushed the icon 8.5px UP
        (measured).

        Writing `none` does NOT BREAK the press effect: that rule is more
        specific (0,4,0) and writes its own `translateY(1px)` when pressed.
        So no translate at rest, 1px down when pressed — exactly the
        desired behaviour. */
    transform: none;

    /*  THE SIZE IS MATCHED TO THE ROW — centring alone was not enough.

        Measured: with centring alone the overflow dropped from 16px to
        4px but did NOT REACH ZERO, because the button is 26px and the row
        it sits in 17px. Something centred in a box smaller than itself
        overflows at both ends.

        `height: 100%` WAS TRIED AND DID NOT HOLD: the wrapper has only a
        `min-height`, no definite size — a percentage cannot resolve
        against such an ancestor and falls to `auto`, the button stayed
        26px.

        The size is written directly: the row's own expression
        (`--row-h - 9px`), i.e. the same source as the input and the
        dropdown. When the density tier changes all three change together. */
    height: calc(var(--row-h) - 9px);
    min-height: 0;
}

/*  THE TRAILING ICON BUTTON MOVES UP TO THE FRAME.

    The rule above seated the button at the CONTENT box's right edge, but
    the eye takes the frame as reference. Measured — **15px** between the
    icon's visible right edge and the frame:

        1px border + 8px field padding (--sp-3) + ~6px space inside the button

    The same 15px was on the dropdown's arrow too, so the two controls
    were consistent with each other but both sat inside.

    THE FIELD'S HORIZONTAL PADDING IS FOR THE TEXT. The text must not stick
    to the border; the trailing icon button however should read as part of
    the frame. So that padding does not apply to the control here and the
    buttons move over it.

    Moved with `margin`, not by changing the `right` values: in Radzen the
    clear cross's position depends on the trigger's WIDTH (`right: 26px`).
    Recomputing the two separately would pin that width here and the day
    the icon size changed the gap between them would break. Applying the
    same margin to both keeps their relation.

    `transform` WAS USED FIRST AND IT WAS FRAGILE (K-168): our press effect
    (`.rax-shell .rz-button…:active`, (0,4,0)) overrides this rule (0,2,0)
    and since `transform` is one property the arrow jumped 8px LEFT when
    pressed. The same defect on the calendar button was reported by the
    user; this one was silent.

    The remaining gap is ~7px: not stuck, a deliberate optical margin. */
/*  The calendar button is NOT in this list: its rule is separate, because
    its size is also matched to the row there. Its translate however is
    NOW THE SAME, horizontal only (K-167) — vertical centring moved to
    `inset-block` + `margin-block: auto` and got free of `transform`.

    The two used to be merged into one `transform` and that was fragile:
    `transform` is one property, someone writing a second rule overrides
    it entirely. Now even if it is overridden the centring stays up. */
.rax-field .rz-dropdown-trigger,
.rax-field .rz-dropdown-clear-icon,
.rax-lines .rz-dropdown-trigger,
.rax-lines .rz-dropdown-clear-icon {
    margin-inline-end: calc(-1 * var(--sp-3));
}

/* The checkbox should sit left-aligned inside the frame. */
.rax-field .rz-chkbox {
    margin-block: 2px;
    margin-inline: 0;
}

/* ----------------------------------------------------------
   PICK-FROM-SCREEN BOX

   The dropdown's sibling: it lives inside the same frame (`.rax-field`),
   keeps the same height, reads the same tokens. The difference is its
   content — not an input but a VALUE and two commands.

   The height is given with the same calculation derived from `--row-h`;
   looking at the form, whether a field is a lookup or a picker must not
   show from the row height.
   ---------------------------------------------------------- */
.rax-pick {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
    width: 100%;
    min-height: calc(var(--row-h) - 9px);
}

/*  THE VALUE GROWS, THE BUTTONS DO NOT.

    Without `min-width: 0` a long title inflates the flex box and pushes
    the buttons outside the field — a `flex` item's default minimum size
    is its content, not zero. */
/*  Its size is written: the box is NOT an input (the choice is made on a
    screen), so it does not get Radzen's input size and fell to the body
    by inheritance. The value must be the same size in both modes of the
    same field — it reads whatever the input reads. */
.rax-pick-val {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--fs-table);
    line-height: var(--lh-tight);
}

/* An empty field reads like a placeholder: "Seçiniz" is not a value, it
   is the name of absence. */
.rax-pick[data-empty='true'] .rax-pick-val {
    color: var(--c-ink-3);
}

/*  The buttons are in the icon font and FRAMELESS: the field already has
    its own frame, a second border inside would make a double line (the
    same decision was made for the inputs inside `.rax-field`).

    THE SIZE IS NOT FIXED, IT COMES FROM THE FIELD'S LEVER: 18px was
    written and in dense mode it exceeded the field's own size (17px) by
    1px — measured, the lookup field 30px, its neighbours 29px. "Whether a
    field is a lookup must not show from the row height" is WRITTEN above;
    a fixed pixel broke it when the density changed. */
.rax-pick-btn,
.rax-pick-x {
    display: grid;
    place-items: center;
    flex: none;
    width:  calc(var(--row-h) - 9px);
    height: calc(var(--row-h) - 9px);
    padding: 0;
    border: none;
    border-radius: var(--r-control);
    background: transparent;
    color: var(--c-ink-3);
    font-family: 'Material Symbols', 'Material Icons';
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
    transition: color var(--motion) var(--motion-ease),
                background-color var(--motion) var(--motion-ease);
}

.rax-pick-btn:hover,
.rax-pick-x:hover {
    background: var(--c-accent-bg);
    color: var(--c-accent);
}

/* For the keyboard user: the field's own focus colour is on the box's
   frame, the button's focus must show here. */
.rax-pick-btn:focus-visible,
.rax-pick-x:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
    color: var(--c-accent);
}

/* ============================================================
   DROPDOWN PANELS — lookup, date, search, filter

   When these panels open Radzen MOVES them to `body`: no rule written
   under `.rax-shell` or `.rax-field` reaches them. So they are written
   here with a root selector.

   They keep reading tokens — since `[data-design]` is on html, the
   variables are inherited by `body` too; when the design changes the
   panel changes. The only things needing a rule are three things with NO
   counterpart among Radzen's own variables: border, row height and font
   size.
   ============================================================ */

/*  THE PANEL HAS ITS OWN LINE.

    Radzen separates the panel only by shadow (`border: none` measured).
    Leaving the boundary of a white panel on a white card to the shadow is
    not enough — in this repository elevation is already muted
    (`--rz-shadow-*` bound to tokens and soft on purpose), so the thing
    carrying the separation is a line. The decision "a line separates, not
    a shadow" is written in tokens.css; the panel had been left out of it. */
/*  A CLOSED PANEL IS NEVER DRAWN — and this rule comes BEFORE the one below.

    Defect: when the record form first opened, a thin vertical line stood
    to the right of the selected value, right in the middle of the box.
    That it happened "at the first moment" is no coincidence.

    Measured: `.rz-dropdown-panel` is in the DOM and in the flow while
    closed — **2px wide, 304px tall, x=464** (the box 302→628, so exactly
    its middle). The `border` and white background given to it in a rule
    below painted this near-zero-width box as a thin line.

    So the line was the border we added ourselves. Radzen writes
    `display:none` AFTER opening and closing the panel; at the first
    render it has not written it yet and that painted gap is the moment
    the user sees.

    The `rz-open` class says the panel is open (measured). A closed one is
    never drawn; Radzen's own show/hide logic is not touched, only the gap
    at the first render is closed. */
.rz-dropdown-panel:not(.rz-open),
.rz-autocomplete-panel:not(.rz-open),
.rz-multiselect-panel:not(.rz-open) {
    display: none;
}

.rz-dropdown-panel,
.rz-autocomplete-panel,
.rz-multiselect-panel,
.rz-datepicker-panel,
.rz-overlaypanel {
    border: 1px solid var(--c-line-2);
    border-radius: var(--r-card);
    background: var(--c-surface);
}

/*  THE DROPDOWN TABLE'S GRID STAYS WHITE.

    The screen's background was pulled to the canvas and the grid's general
    background went with it (tokens.css). But this grid is not on the
    screen, it is INSIDE THE PANEL: the panel is a surface standing "on top
    of the paper" and in the same colour as its background it does not
    read as floating. */
.rz-dropdown-panel .rz-data-grid,
.rz-dropdown-panel .rz-datatable {
    background: var(--c-surface);
}

/*  CLIPPING IS WRITTEN ONLY ON LIST PANELS.

    Needed so a row does not overflow inside the rounded corner.

    `.rz-overlaypanel` (calendar, grid filter) is NOT in the list, not
    because it does not need it — Radzen already gives it
    `overflow: hidden` itself (measured). Writing it again would be a dead
    rule. */
.rz-dropdown-panel,
.rz-autocomplete-panel,
.rz-multiselect-panel {
    overflow: hidden;
}

/*  NO SEARCH ICON IN THE DROPDOWN (K-158).

    Radzen puts a magnifier next to the filter box
    (`span.rz-dropdown-filter-icon`). What the box is for is already clear
    — focused, the cursor inside, typing filters the list. The icon adds no
    information, it narrows the box.

    THE THIRD APPLICATION OF THE SAME DECISION: in the grid picker
    (`.rz-lookup-search > .rz-button`) it was hidden for the same reason
    too. One rule: a dropdown is a surface, not a toolbar.

    `display: none` IS SAFE, measured: the container is `flex` and the icon
    `static` — once it stops taking room the input widens, no gap is left
    behind. With `visibility: hidden` a 19.5px dead area would remain. */
.rz-dropdown-filter-container > .rz-dropdown-filter-icon,
.rz-multiselect-filter-container > .rz-multiselect-filter-icon {
    display: none;
}

/*  THE FILTER BOX DOES NOT STICK TO THE EDGE (K-159).

    Radzen gives the container `13px 0 6.5px` — ZERO on the sides. The
    box's focus frame touched the panel's border and two lines overlapped.

    The size is THE SAME as the grid picker's (`.rz-lookup-search`,
    `var(--sp-2)`): both surfaces do the same job and should breathe the
    same.

    The vertical was equalised too. Radzen's 13/6.5 asymmetry pushed the
    box down; symmetric padding centres it. */
.rz-dropdown-filter-container,
.rz-multiselect-filter-container {
    padding: var(--sp-2);
}

/* ------------------------------------------------------------
   DROPDOWN TABLE — NOT A DIALOG, A DROPDOWN

   Radzen's `RadzenDropDownDataGrid` opens like a small dialog by default.
   Measured:

     .rz-lookup-panel      13px inner padding — tears the boxes from the edge
     .rz-lookup-search     a separate MAGNIFIER BUTTON next to the box
     .rz-pager             a 52px pager (drawn even though paging is off)
     scrolling             on the panel ITSELF — the search box and the
                           header row scroll up out of sight too

   All four are things a dropdown should not have: a dropdown is a
   surface, not a second screen.
   ------------------------------------------------------------ */

/*  Padding ZERO: the panel itself carries the border (the rule above); a
    second frame allowance inside turned it into a dialog. */
.rz-lookup-panel {
    padding: 0;
}

/*  THE SEARCH IS ONLY THE BOX.

    What the magnifier button does, typing into the box already does —
    the search goes to the server on every key. The button is not a second
    way but a repeat of the same way; besides, being in the accent colour
    it was the most eye-catching thing in the panel. */
.rz-lookup-panel .rz-lookup-search {
    padding: var(--sp-2);
    border-block-end: 1px solid var(--c-line);
}

.rz-lookup-panel .rz-lookup-search > .rz-button {
    display: none;
}

.rz-lookup-panel .rz-lookup-search-input-container {
    width: 100%;
}

/* The box speaks the same language as the picker's search box (`.rax-list-search`). */
.rz-lookup-panel .rz-lookup-search-input {
    width: 100%;
    height: var(--row-h);
    padding: 0 var(--sp-3);
    border: 1px solid var(--c-line-2);
    border-radius: var(--r-control);
    background: var(--c-surface);
    color: var(--c-ink);
    font-family: inherit;
    font-size: var(--fs-table);
}

/* One frame (see `.rax-pagerx-input:focus`). */
.rz-lookup-panel .rz-lookup-search-input:focus {
    outline: none;
    border-color: var(--c-accent);
    box-shadow: none;
}

/*  NO PAGER.

    The list is already limited on the server (50) and the way to narrow
    it is the search. Turning pages in a dropdown takes the user away from
    making a choice — with many records the right tool is a pick-from-screen
    picker (`LookupPick.Screen`), not a paged dropdown. */
.rz-lookup-panel .rz-pager {
    display: none;
}

/*  SCROLLING IS IN THE GRID, NOT THE PANEL.

    When the panel scrolled, the search box and header row scrolled up and
    vanished — the user had to scroll back to see the box to type into.
    Scrolling moved down to where the rows are; the box and the header
    stay in place.

    The header is `sticky`: while the rows flow "Kod / Ad" stays visible.
    What makes a table a table is the names of its columns. */
.rz-lookup-panel .rz-data-grid-data {
    max-height: calc(var(--row-h) * 10);
}

.rz-lookup-panel thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--c-surface-2);
}

/*  THE ROW HEIGHT IS THE SAME AS THE GRID'S.

    `min-height` gives the size, not padding: when vertical padding and
    height add up the row doubles (this trap was fallen into once inside
    `.rax-field`, the note is there).

    `display: flex` + centring seats the `<li>`'s text on its own height,
    not the line box; otherwise the text sticks to the top in a 26px row.

    THE FONT SIZE IS NOT HERE but in the `--rz-dropdown-item-font-size`
    variable in tokens.css: Radzen's selector (`.rz-dropdown-items li`) is
    more specific than the single-class selector here and beats the rule.
    Measured, tried, did not hold. */
.rz-dropdown-item,
.rz-autocomplete-list-item,
.rz-multiselect-item {
    display: flex;
    align-items: center;
    min-height: var(--row-h);
    line-height: var(--lh-tight);
}

/* ----------------------------------------------------------
   CONSULTANT EDITOR (Phase 2)

   Colour and size from tokens (K-036). A changed row is marked with the
   accent on its left edge: the consultant must see at a glance what they
   touched, the question "what changed before saving" must not arise.
   ---------------------------------------------------------- */

.rax-overlay-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-body);
}

.rax-overlay-table th {
    text-align: left;
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--c-ink-3);
    padding: var(--sp-3) var(--sp-3);
    border-bottom: 1px solid var(--c-line-2);
    background: var(--c-surface-2);
}

.rax-overlay-table td {
    padding: var(--sp-2) var(--sp-3);
    border-bottom: 1px solid var(--c-line);
    vertical-align: middle;
}

.rax-overlay-table td.center { text-align: center; }

.rax-overlay-table .name {
    font-family: var(--font-code);
    font-size: var(--fs-dense);
    color: var(--c-ink-2);
}

.rax-overlay-table .required {
    color: var(--c-accent);
    font-weight: var(--fw-medium);
    margin-inline-start: var(--sp-1);
}

/* A row deviating from the core. The left edge, not the background: so
   row height and readability are not disturbed. */
.rax-overlay-table tr.changed td:first-child {
    box-shadow: inset 3px 0 0 var(--c-accent);
}

/*  THE CUSTOMISATION SCREEN'S BOXES ARE THE SAME SIZE TOO. The two
    selectors here wrote `--fs-body` with no reason and the result was:
    the same field's box one size on the record screen and another on the
    customisation screen. Type does not change with the screen's job — the
    size's only author is the `--rz-input-font-size` bridge. */

/* A field added by the tenant (K-049). The same language as the required
   asterisk but a different colour: one states a constraint, the other an
   origin. */
.rax-overlay-table .added {
    color: var(--c-ink-3);
    font-weight: var(--fw-medium);
    margin-inline-start: var(--sp-1);
}

.rax-overlay-editor .rax-hint {
    display: block;
    margin-top: var(--sp-3);
    color: var(--c-ink-3);
}

/* ------------------------------------------------------------
   THE CUSTOMISATION DIALOG'S SCROLL CHAIN

   An exact copy of the layout designer's
   (`.rz-dialog-content:has(> .rax-designer)`), the only difference is the
   scope. Two dialogs behaved differently inside the same container: in
   the designer the strip stayed put, in customisation the command row
   scrolled with the content.

   The scope is locked with `:has` — no other dialog is affected.
   ------------------------------------------------------------ */
.rz-dialog-content:has(> .rax-overlay-editor) {
    display: flex;
    height: 100%;
    min-height: 0;
}

.rz-dialog-content > .rax-overlay-editor {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
}

/* The SCROLLING part. Horizontal overflow is off: the table already fits
   the container and left `auto`, Radzen's grid showed a horizontal bar at
   a one-pixel rounding difference. */
.rax-overlay-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

/* The FIXED part. The same divider as the record dialog's command strip —
   there `border-bottom` because the strip is on top, here `border-top`
   because the command row is at the bottom. */
.rax-overlay-bar {
    flex: none;
    padding-block-start: var(--sp-3);
    border-block-start: 1px solid var(--c-line);
}

/* ============================================================
   SCREEN DESIGNER  (Phase 5, stage 1)

   Three panes + a fixed command strip. The REAL form sits inside the
   canvas; the rules here DO NOT TOUCH the form's layout, they only put an
   editing shell over it.

   The split is deliberate: had the designer changed the form's sizes,
   "it looked like this in the designer" bugs would begin.
   ============================================================ */

.rax-designer {
    display: grid;
    grid-template-columns: 200px minmax(0, 1fr) 230px;
    grid-template-rows: minmax(0, 1fr) auto;
    gap: var(--sp-4);
    height: 100%;
    min-height: 0;
}

.rax-designer-tools,
.rax-designer-props {
    min-height: 0;
    overflow-y: auto;
    padding: var(--sp-3);
    background: var(--c-surface-2);
    border: 1px solid var(--c-line);
    border-radius: var(--r-card);
}

/* The canvas is the SCROLLING part. The strip and panes stay fixed — the
   same scroll chain as the list and record screens. */
/*  THE CANVAS'S BACKGROUND IS NOW THE RECORD CARD'S BACKGROUND (K-191).

    It was white and that broke the designer's own promise: «there is no
    preview button, the canvas itself is the preview». Measured —

        designer canvas     → rgb(255,255,255)   (--c-surface)
        real record card    → #F7F6F3            (--c-canvas)

    Fields have NO background, only a frame (K-087): the same frame read
    one way on a white background and another in production. Once the
    canvas took the real card's values the difference closed.

    The padding is --form-pad for the same reason: the real form's body
    (.rax-form-body, shell.css) uses that token. Left at --sp-4, the fields
    would sit closer to the card's edge than in production and the
    difference would grow when the density tier changed. */
.rax-designer-canvas {
    min-height: 0;
    overflow: auto;
    padding: var(--form-pad);
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--r-card);

    /* The paper sits on the workbench (K-196). The background DOES NOT
       CHANGE — it is the real record card's colour; the surface below and
       this shadow make the separation. */
    box-shadow: var(--sh-1);
}

/*  TITLE IN SECONDARY INK, HINT IN TERTIARY (K-196).

    Measured: the title, the empty pane message and the counter were ALL
    THREE --c-ink-3 (#6B6B6D, contrast 5.09). Caps and letter spacing set
    the title apart, but on the colour channel three roles fell to one
    tier. The title moved up to --c-ink-2; the hints stayed, so the tiers
    now exist in COLOUR too. */
.rax-designer-tools h3,
.rax-designer-props h3 {
    margin: 0 0 var(--sp-3);
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--c-ink-2);
}

.rax-designer-props h3 {
    font-family: var(--font-code);
    text-transform: none;
    letter-spacing: 0;
    color: var(--c-ink);
}


.rax-designer-props label {
    display: block;
    margin: var(--sp-4) 0 var(--sp-2);
    font-size: var(--fs-caption);
    color: var(--c-ink-3);
}

.rax-designer-props label.row {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    color: var(--c-ink-2);
}

.rax-designer-empty,
.rax-designer-note {
    margin: var(--sp-3) 0 0;
    font-size: var(--fs-caption);
    line-height: 1.45;
    color: var(--c-ink-3);
}

/* A field in the toolbox. The same drag language as a field on the canvas:
   the same handle icon, the same cursor. */
.rax-designer-chip {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin-bottom: var(--sp-2);
    padding: var(--sp-2) var(--sp-3) var(--sp-2) var(--sp-2);
    background: var(--c-surface);
    border: 1px solid var(--c-line);
    border-radius: var(--r-control);
    font-size: var(--fs-body);
    cursor: grab;
}

.rax-designer-chip:hover { border-color: var(--c-line-2); }
.rax-designer-chip .label { flex: 1 1 auto; min-width: 0; }

.rax-designer-chip .section {
    font-size: var(--fs-caption);
    color: var(--c-ink-3);
}

.rax-designer-chip .rzi,
.rax-design-grip .rzi {
    font-size: 16px;
    color: var(--c-ink-3);
}

/* ------------------------------------------------------------
   A FIELD ON THE CANVAS

   `pointer-events: none` goes INSIDE the field: a click finds the
   wrapper, not the editor. In design mode a click SELECTS, it does not
   enter data — there is no record to enter into anyway.
   ------------------------------------------------------------ */

.rax-design-slot {
    position: relative;
    padding-inline-start: var(--sp-6);
    border: 1px dashed transparent;
    border-radius: var(--r-control);
    cursor: grab;
}

.rax-design-slot > .rax-field,
.rax-design-slot > .rax-field-error { pointer-events: none; }

.rax-design-slot:hover {
    border-color: var(--c-line-2);
    background: var(--c-touch);
}

.rax-design-slot.selected {
    border-style: solid;
    border-color: var(--c-accent);
    background: var(--c-accent-bg);
}

.rax-design-slot.dragged { opacity: .4; }

/*  THE HANDLE WENT QUIET, IT DID NOT DISAPPEAR (K-191).

    In a nine-field form nine handles stood in full ink and all said the
    same thing: «draggable». Measured — opacity 1 on all nine of the nine
    slots on the canvas. The form itself is what is to be read; the handle
    is its edge ornament.

    NOT SWITCHED OFF, TURNED DOWN. K-188's lesson forbids it: a feature
    existing does not make it usable, an invisible handle is an untried
    handle. On hover and when selected it returns to full ink — so wherever
    the eye looks, it is sharp. */
.rax-design-grip {
    position: absolute;
    inset-block-start: 50%;
    inset-inline-start: var(--sp-1);
    transform: translateY(-50%);
    display: flex;
    pointer-events: none;
    opacity: .38;
    transition: opacity var(--motion) var(--motion-ease);
}

.rax-design-slot:hover .rax-design-grip,
.rax-design-slot.selected .rax-design-grip { opacity: 1; }

/* The end of the section — ONLY WHILE DRAGGING (K-186).
   First it stood there all the time and the reason was: "for the target
   to APPEAR during dragging we would have to listen to `dragenter` and
   that is the event that floods the circuit on Blazor Server." The reason
   was right but incomplete — appearing is a LOOK job and the browser can
   do it alone. `rax.js` writes the class, it never goes to the circuit.
   Gain: a dashed box standing under every section while the user dragged
   nothing was an invitation with nothing behind it. */
.rax-design-tail {
    display: none;
    margin-block-start: var(--sp-2);
    padding: var(--sp-3);
    border: 1px dashed var(--c-line-2);
    border-radius: var(--r-control);
    text-align: center;
    font-size: var(--fs-caption);
    color: var(--c-ink-3);
}

.rax-designer.dragging .rax-design-tail {
    display: block;
    animation: rax-belir var(--motion-panel) ease-out;
}

@keyframes rax-belir {
    from { opacity: 0; transform: translateY(-2px); }
    to   { opacity: 1; transform: none; }
}

.rax-design-tail:hover {
    border-color: var(--c-accent);
    color: var(--c-accent);
}

/* ------------------------------------------------------------
   COMMAND STRIP
   ------------------------------------------------------------ */

/* THE STRIP SPANS ALL THREE COLUMNS (K-190).

   It did not and the grid placed it automatically: in the FIRST column
   of the second row, i.e. under the 240px toolbox. Measured — the buttons
   were clipped to «Sıf», «Ger al», «Yay». The strip is a FRAME element;
   it does not belong under one of the panes. */
.rax-designer-bar {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding-block-start: var(--sp-3);
    border-block-start: 1px solid var(--c-line);
}

.rax-designer-spacer { flex: 1 1 auto; }

.rax-designer-counter {
    font-size: var(--fs-caption);
    color: var(--c-ink-3);
}

.rax-designer-error,
.rax-designer-warning {
    font-size: var(--fs-caption);
    line-height: 1.45;
}

.rax-designer-error  { color: var(--c-neg); }
.rax-designer-warning { color: var(--c-ink-2); }

/* By default the body of a Radzen modal grows with its content; the
   designer's grid however wants a HEIGHT. The scope is locked to the
   designer with `:has` — no other dialog is affected. */
.rz-dialog-content:has(> .rax-designer) {
    display: flex;
    height: 100%;
    min-height: 0;
    padding: var(--sp-4);
}

.rz-dialog-content > .rax-designer { flex: 1 1 auto; min-width: 0; }

/* ============================================================
   ENTITY DESIGNER  (Phase 5, layer 2)

   The same language as the layout designer's grid, one row more: the
   entity header on top. The field card and the selected state are SHARED
   with `.rax-designer-chip` — the two designers speaking the same drag
   language is deliberate.
   ============================================================ */

/*  THE SIZES ARE THE SAME AS THE LAYOUT DESIGNER'S (K-196).

    At one time `196px … 218px / gap 8 / padding 8` was written here while
    the layout designer used `240px … 280px / gap 12 / padding 12`. The two
    screens are the same archetype — palette · canvas · properties — and
    carried two separate size systems. K-189 had shared the palette, K-192
    the drawing; the FRAME had stayed separate.

    The widening also closes a complaint: K-193 had measured the scope
    badges wrapping at the SECOND scope in the 196px pane and found the
    cure in stacking them. At 240px a badge finds its own width.

    The cost was measured: canvas 799 → 715px. The layout designer's
    canvas is already 669px and shows the same form; the narrow side was
    the reference, the wide side the exception. */
.rax-studio {
    display: grid;
    grid-template-columns: 240px minmax(0, 1fr) 280px;
    grid-template-rows: auto minmax(0, 1fr) auto;
    gap: var(--sp-4);
    height: 100%;
    min-height: 0;
    padding: var(--sp-4);
    background: var(--c-desk);
}

/*  THE STRIP MUST STAY ON ONE LINE.

    Measured: when it overflowed to two lines not only did its own height
    go up to 131px — it took that much room from the canvas below too, so
    the design's real surface shrank for the sake of a header.

    The boxes were narrowed and the gaps reduced. `flex-wrap` stays: on a
    narrow screen overflowing beats being clipped. */
.rax-studio-head {
    grid-column: 1 / -1;
    display: flex;
    align-items: flex-end;
    gap: var(--sp-3);
    flex-wrap: wrap;
    padding-block-end: var(--sp-3);
    border-block-end: 1px solid var(--c-line);
}

/* What pushes to the right is NOT an empty element but a margin: an empty
   element took its own line when the strip wrapped (measured, 124px). */
.rax-studio-head .end { margin-inline-start: auto; }

/*  THE WIDTH IS NOW THE INPUT'S JOB, NOT THE CONTAINER'S.

    `.narrow` wrote 62px on a wrapper `<div>`. Once the wrapper became
    `fieldset.rax-field` that 62px also covered the frame and the input was
    left with 62 − 2×(--sp-3) − 2px; the box came out narrower than the
    number inside. The size is on the input, the container grows with its
    content. */
.rax-studio-head .rz-textbox,
.rax-studio-head .rz-dropdown { width: 130px; }
.rax-studio-head .narrow .rz-numeric { width: 62px; }

/*  THE FIELD LABEL IS INSIDE THE FRAME — the same as the record screen.

    This block once also covered `.rax-studio-head label` and
    `.rax-studio-props label`, i.e. it put uppercase + .04em letter spacing
    on the FIELD LABEL. Measured: that language is the language of the
    SECTION TITLE in the standard form (`.rax-form .rz-fieldset > legend`).
    On the same screen the field label and the section title looked the
    same — the hierarchy was off by one tier and the designer read like
    «another application».

    Field labels moved to `fieldset.rax-field` + `legend` and take their
    style from there. The two consumers LEFT here are really titles: the
    pane titles (`h3`) and the `<label>`s naming a group
    («Nereden seçilecek», «Seçenekler»).

    `.rax-designer-props label` was NOT PUT ON THIS LIST: in the layout
    designer only the checkbox row remains and its own rule is above (NOT
    uppercase). */
.rax-studio-props label,
.rax-studio-fields h3,
.rax-studio-props h3 {
    display: block;
    margin: 0 0 var(--sp-2);
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--c-ink-2);   /* K-196 — the hints stayed at --c-ink-3 */
}

.rax-studio-props label { margin-top: var(--sp-4); }

/*  THE PANE TITLES ARE STICKY (K-191).

    All four panes scroll inside themselves (overflow-y: auto) and the
    title scrolled away: in a long field list, once past «Formda değil»
    the user lost which list they were looking at, and in the properties
    pane WHICH FIELD they were editing. The title on the right is the
    selected field's NAME — the first thing that must not vanish on
    scrolling.

    THE TOP OFFSET IS NOT ZERO BUT MINUS THE PADDING. In a scrolling
    container inset-block-start: 0 sticks the title to the container's
    PADDING edge and a strip of content stays visible above it; with the
    title pulled up by the padding and given the same inner padding, that
    strip also stays under the title's background.

    The background is THE SAME as the pane's: with a separate colour a
    second surface would be born inside the pane and the eye would read it
    as a separate box.

    THE RULE IS HERE, NOT ABOVE. It had been written in the layout
    designer's section and did not work: in this file the
    `.rax-studio-fields h3` rule comes LATER, rewrites the `margin`
    shorthand and at equal specificity the later one wins — so the top
    space went back to zero (K-062's lesson, this time as ordering). */
.rax-designer-tools h3,
.rax-designer-props h3,
.rax-studio-fields h3,
.rax-studio-props h3 {
    position: sticky;
    z-index: 1;
    background: var(--c-surface-2);
}

/*  THE OFFSET IS THE PANE'S OWN TOP PADDING.

    This rule was once SPLIT IN TWO and the reason was right: the padding
    was --sp-3 in the layout pane and --sp-2 in the entity pane; with a
    single value written one would be exposed and the other would overlap
    the border. Once K-196 gave both panes the same padding the split
    became unnecessary — the rule became one together with its reason. */
.rax-designer-tools h3,
.rax-designer-props h3,
.rax-studio-fields h3,
.rax-studio-props h3 {
    inset-block-start: calc(-1 * var(--sp-3));
    margin-block-start: calc(-1 * var(--sp-3));
    padding-block: var(--sp-3) var(--sp-2);
}

/*  Fields in the pane are full width with their own vertical rhythm.
    Fields in the strip grow with their content — there the line is
    single and room is tight. */
.rax-studio-props .rax-field,
.rax-designer-props .rax-field {
    width: 100%;
    margin-block-start: var(--sp-3);
}

/*  No top margin so the pane's FIRST field does not stick to the title:
    `h3` already gives its own bottom margin and when both stacked the
    space between the title and the box doubled. */
.rax-studio-props h3 + .rax-field,
.rax-designer-props h3 + .rax-field { margin-block-start: 0; }

.rax-studio-props label.row {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    text-transform: none;
    letter-spacing: 0;
    font-size: var(--fs-body);
    color: var(--c-ink-2);
}

/*  SCOPE STRIP — the main record and the detail collections.

    NOT a field card but a tab: a card selects one thing, this changes
    what the whole pane shows. So its visual language is separate from
    `.rax-designer-chip` — had the two looked the same it would be "I
    clicked the collection, I thought a field was selected".

    STACKED (K-193). First it was a wrapping row and the reason was right
    — «the number of collections is unlimited, dropping down beats
    clipping in a narrow pane» — but the result was measured: in the 196px
    pane it already wrapped at the second scope and the wrapped badges
    read not like tabs but like scattered labels. A list that may wrap
    should be laid out as a list from the start. */
.rax-studio-scopes {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    margin-block-end: var(--sp-3);
}

/*  THE BUTTONS ARE FULL WIDTH AND HAVE ICONS (K-193).

    First they were small badges side by side and did not say two things:
    which one is what (main record or line table) and what the add button
    adds — the latter was only in the `title` tooltip, so whoever did not
    hover did not see it.

    Now they are laid out row by row: in a 196px pane three badges side by
    side already wrapped and wrapped badges read not like «tabs» but like
    scattered labels. Stacked full-width boxes keep the same rhythm as the
    rest of the left pane (field cards, palette rows). */
.rax-studio-scopes button {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    inline-size: 100%;
    padding: var(--sp-2) var(--sp-3);
    border: 1px solid var(--c-line-2);
    border-radius: var(--r-control);
    background: var(--c-surface);
    color: var(--c-ink-2);
    font-family: inherit;
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    line-height: var(--lh-tight);
    text-align: start;
    cursor: pointer;
    transition: background-color var(--motion) var(--motion-ease),
                border-color var(--motion) var(--motion-ease),
                color var(--motion) var(--motion-ease);
}

/*  THE ICON TELLS THE SCOPE'S KIND: card (`description`) and line table
    (`table_rows`). It used to be read from the order — the first was the
    main record — and an order is not a sign, it is a coincidence. */
.rax-studio-scopes button .rzi {
    font-size: 16px;
    color: var(--c-ink-3);
}

.rax-studio-scopes button:hover:not([data-on='true']) {
    background: var(--c-touch);
    color: var(--c-ink);
}

.rax-studio-scopes button[data-on='true'] {
    background: var(--c-accent-bg);
    border-color: var(--c-accent);
    color: var(--c-accent);
}

.rax-studio-scopes button[data-on='true'] .rzi { color: var(--c-accent); }

/* The add button is NOT a scope: it cannot be selected, so it gets no
   `data-on` and is set apart with a dashed frame. In the repository a
   dashed frame already means «something will come here» —
   `.rax-design-tail` and `.rax-designer-drop` use the same sign. */
.rax-studio-scopes button.add {
    border-style: dashed;
    color: var(--c-ink-3);
}

.rax-studio-scopes button.add:hover {
    border-color: var(--c-accent);
    color: var(--c-accent);
}

.rax-studio-scopes button.add:hover .rzi { color: var(--c-accent); }

/* The padding is also the same as the layout designer's panes (K-196): a
   separate value split the sticky title offset below in two as well. */
.rax-studio-fields,
.rax-studio-props {
    min-height: 0;
    overflow-y: auto;
    padding: var(--sp-3);
    background: var(--c-surface-2);
    border: 1px solid var(--c-line);
    border-radius: var(--r-card);
}

/* The SAME background, padding and reason as the layout designer's
   canvas (K-191): both show the real record card. With separate values
   the same form would appear on two different backgrounds in the two
   designers. */
.rax-studio-canvas {
    min-height: 0;
    overflow: auto;
    padding: var(--form-pad);
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--r-card);
    box-shadow: var(--sh-1);
}

/* The rule for the type label on the field card was DELETED in K-193: the
   markup no longer carries `.tip`, so the rule was dead (the first
   direction of K-170). The type is read from the shape of the control on
   the canvas (K-192). */

.rax-designer-chip.selected {
    border-color: var(--c-accent);
    background: var(--c-accent-bg);
}

.rax-designer-chip.dragged { opacity: .4; }

.rax-studio-bar {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding-block-start: var(--sp-2);
    border-block-start: 1px solid var(--c-line);
}

.rax-studio-result {
    font-size: var(--fs-caption);
    line-height: 1.45;
    color: var(--c-ink-2);
}

.rax-studio-result code,
.rax-studio-props code {
    font-family: var(--font-code);
    font-size: var(--fs-caption);
    color: var(--c-ink);
}

/* The generated source. It opens not ABOVE the canvas but below it:
   seeing the preview and the source in turn rather than side by side
   keeps both readable on a narrow screen. */
.rax-studio-source {
    grid-column: 1 / -1;
    max-height: 40vh;
    overflow: auto;
    margin: 0;
    padding: var(--sp-4);
    background: var(--c-surface-2);
    border: 1px solid var(--c-line);
    border-radius: var(--r-card);
    font-family: var(--font-code);
    font-size: var(--fs-caption);
    line-height: 1.5;
    white-space: pre;
}

/* Choice list row. The number is on the LEFT and read-only: that is what
   gets written to the database, looking editable would be a false
   invitation. */
.rax-studio-option {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin-block-start: var(--sp-1);
}

.rax-studio-option .no {
    flex: none;
    min-width: 22px;
    text-align: right;
    font-family: var(--font-code);
    font-size: var(--fs-caption);
    color: var(--c-ink-3);
}

/* ------------------------------------------------------------
   ICON PICKER

   Icons are drawn as REAL GLYPHS, not as a list of names: the picker's
   benefit is not validation but seeing — a name that does not resolve
   shows as text here and is noticed before publishing.
   ------------------------------------------------------------ */

.rax-studio-icon {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
}

/* The preview glyph is a BUTTON: a second, larger target opening the
   picker. A 26px icon-only button could not be found on its own. */
.rax-studio-icon .preview {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 30px;
    height: 30px;
    padding: 0;
    background: var(--c-surface);
    border: 1px solid var(--c-line);
    border-radius: var(--r-control);
    color: var(--c-ink-2);
    cursor: pointer;
}

.rax-studio-icon .preview:hover {
    border-color: var(--c-accent);
    color: var(--c-accent);
}

.rax-studio-icon .preview > span {
    font-family: 'Material Symbols', 'Material Icons';
    font-size: 19px;
    line-height: 1;
}

/*  AN OVERLAY, NOT A GRID ROW.

    First it was a direct child of the `.rax-studio` grid and it was
    measured: `grid-template-rows: 131px 0px 362px 35px`. It had grabbed
    the `1fr` row meant for the three panes; when the panes slid to an
    implicit `auto` row there was no spare room left for `1fr` and the
    picker was drawn at ZERO height. The panel was "open" but invisible.

    It is positioned against its trigger (`.rax-studio-icon`
    `position: relative`), so it no longer eats a row or lengthens the
    screen. */
.rax-studio-icon { position: relative; }

.rax-studio-icons {
    position: absolute;
    z-index: 20;
    inset-block-start: calc(100% + var(--sp-2));
    inset-inline-start: 0;
    width: 340px;
    max-height: 46vh;
    overflow: auto;
    padding: var(--sp-3);
    background: var(--c-surface);
    border: 1px solid var(--c-line-2);
    border-radius: var(--r-card);
    box-shadow: var(--sh-3);
}

.rax-studio-icons header {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    margin-block-end: var(--sp-3);
}

.rax-studio-icons header .spacer { flex: 1 1 auto; }

.rax-studio-icons h4 {
    margin: var(--sp-4) 0 var(--sp-2);
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--c-ink-3);
}

/*  NO NAME IS WRITTEN, ONLY THE GLYPH.

    First each box had the name too and the grid forced 84px cells — 105
    icons did not fit without filling the screen. What is searched for in
    this grid is the glyph anyway; the name stays in `title` and is
    written to the box when selected. */
.rax-studio-icons .grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(34px, 1fr));
    gap: var(--sp-1);
}

.rax-studio-icons button {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 34px;
    padding: 0;
    background: var(--c-surface);
    border: 1px solid transparent;
    border-radius: var(--r-control);
    cursor: pointer;
    color: var(--c-ink-2);
    overflow: hidden;
}

.rax-studio-icons button > span {
    font-family: 'Material Symbols', 'Material Icons';
    font-size: 20px;
    line-height: 1;
}

.rax-studio-icons button:hover {
    border-color: var(--c-accent);
    color: var(--c-ink);
}

.rax-studio-icons button[data-on="true"] {
    border-color: var(--c-accent);
    background: var(--c-accent-bg);
    color: var(--c-accent);
}

.rax-designer-note.warning { color: var(--c-neg); }

/* ------------------------------------------------------------
   DESIGN SCREEN — TIGHTENING

   Measured: a field card was 42px, the space between pane titles and
   labels 12px. In a six-field entity the list ate half the pane and the
   canvas (the real surface) was squeezed.

   Only the SPACING changes; font sizes and colours stay. So as not to
   clash with the density picker's tiers no rule reads a density token
   like `--row-h`.
   ------------------------------------------------------------ */

.rax-studio-fields h3,
.rax-studio-props h3 { margin-block-end: var(--sp-2); }

.rax-studio-head label { margin-block-end: var(--sp-1); }

.rax-studio-props label { margin-block-start: var(--sp-3); }

.rax-studio-fields .rax-designer-chip {
    margin-bottom: var(--sp-1);
    padding: var(--sp-1) var(--sp-2);
}

/* The section frame on the canvas narrows too: what is shown in design
   mode is layout, not data. */
.rax-studio-canvas .rz-fieldset { margin-block-end: var(--sp-3); }
.rax-studio-canvas .rax-design-tail { padding: var(--sp-2); }

/* ------------------------------------------------------------
   VIEW MODE — A LABEL, NOT A BOX

   A disabled box makes a PROMISE: "you can type here, not right now."
   The user looks for the way to open it. A record to be read has no
   place to type into; a thing that does not exist should not have a box
   either — the view-mode counterpart of the rule "permission does not
   hide, it removes".

   The frame goes too. Emptying the box and leaving the border would be
   half a job: a frame alone says "this is an input".

   THE LAYOUT DOES NOT CHANGE. The same grid, the same columns, the same
   sections — only the frame and padding go. Had it changed, a user
   switching between "İncele" and "Düzelt" would look for the fields
   again every time.
   ------------------------------------------------------------ */

/*  VIEW: THE SAME FRAME, ONE TIER LIGHTER.

    At one point the frame was removed entirely (transparent) and the
    label was faded to be "lighter". Both were wrong:

    * A frameless field loses structure. The line here does not say
      "writable" — it says WHERE WHICH VALUE ENDS and that information is
      needed in view mode too. Without the boundary between two values
      side by side the eye takes them for one text.

    * Fading the text makes it not "light" but UNREADABLE. What is viewed
      is the text itself.

    The only thing that lightens is the LINE: 6% instead of 10%
    (1.23 → 1.13). The label and the value stay in THE SAME ink as edit
    mode.

    The padding stays the same too: for a user switching between the two
    modes the fields stay in the same place at the same size — the only
    thing changing is the line's volume. */
.rax-form-plain .rax-field {
    border-color: var(--c-field-line-soft);
}

/*  The value itself: aligned with the label, full ink colour.

    ITS SIZE COMES FROM THE SAME LEVER AS THE INPUT IN EDIT MODE:
    `calc(var(--row-h) - 9px)`. The "the padding stays the same" note above
    WAS WRITTEN BUT NOT APPLIED — the same as K-062, this time in view
    mode. Measured (dense mode, `--row-h: 26px`):

      View  → value 26px + 2×2px padding, field frame 38px
      Edit  → input 17px,                 field frame 29px

    In a nine-field form this 9px difference showed the form rearranged
    to a user switching between View and Edit. Now both are 17px: the same
    place, the same size, the only change the line.

    `line-height` also dropped from `--lh-body` (1.45 → 18.85px) to
    `--lh-tight`; otherwise the line box would overflow 17px and
    `min-height` would do nothing. Long text still wraps to the next
    line — `min-height` is a floor, not a ceiling. */
/*  THE SIZE COMES FROM THE SAME LEVER AS THE INPUT — THE SAME SPOT A THIRD TIME.

    The note above said "the padding stays the same" and the padding had
    been fixed; the SIZE had not. `--fs-body` is a fixed 13px, while the
    input reads `--fs-table` and that changes with density:

      compact  input 12px · view 13px
      default  input 13px · view 13px   (the same by coincidence)
      wide     input 14px · view 13px

    So the defect was NOT VISIBLE in the default tier. The counterpart of
    the rule "type must not change with the kind of operation" is a single
    token: the field's value is the same size whether edited or viewed. */
/*  THE VALUE TAKES THE SHAPE OF THE INPUT IT REPLACES.

    The note above said «long text wraps to the next line, min-height is a
    floor not a ceiling». It was measured and that sentence produced a
    JUMP: a long customer name wrapped to two lines in view mode, the field
    went from 19px to 32px and came back down when switching to edit — so
    the form's layout changed with the operation.

    A single-line input is replaced by a single-line text: the same height,
    the overflow as an ellipsis. The value is not lost, it stays as `title`
    (DynamicForm writes it).

    Multi-line editors (memo, json) are EXCLUDED from this: their input
    wraps too, so their text wraps. */
/*  CENTRED VERTICALLY IN THE VALUE BOX (K-231).

    `min-height` gave the floor but the text leaned on TOP of that floor:
    in the compact tier the floor equals one line so the difference does
    not show; in the wide tier (--row-h 42px) the text with its 20px line
    sat at the top of the 33px box and moved up compared to edit mode.

    The lever is `line-height`: in single-line text a height equal to the
    line box centres the text exactly. The input does the same (Radzen
    `--rz-input-height` + vertical centring), so the two modes stay in the
    same place.

    NOT VALID FOR MULTI-LINE: there the gap between lines would be 33px.
    `.rax-plain-multi` goes back to the body line height. */
.rax-plain {
    display: block;
    min-height: calc(var(--row-h) - 9px);
    padding-block: 0;
    color: var(--c-ink);
    font-size: var(--fs-table);
    line-height: calc(var(--row-h) - 9px);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.rax-plain-multi {
    line-height: var(--lh-body);
    white-space: pre-wrap;
    overflow: visible;
    overflow-wrap: anywhere;
}

/*  A number is a number while viewed too: `.rax-num` goes next to
    `.rax-plain` (DynamicForm), tabular figures and right alignment come
    from there. The measured difference: in edit mode the number box was
    right-aligned and tabular, in view mode left-aligned and proportional —
    three amounts in the same column did not keep each other's digit
    alignment. */
.rax-plain.rax-num {
    text-align: var(--num-align);
}

/* An empty value is written as a dash: a completely empty line left the
   question "not loaded, or none?". The dash says "looked, none". */
.rax-plain-empty { color: var(--c-ink-3); }

/* ------------------------------------------------------------
   UPDATE SCREEN

   No container of its own: the sections use the record screen's rhythm
   (--sp-*, --c-line, --fs-*). Had we written a separate "system screen"
   language the application would read as made of two pieces — the
   dashboard's and designer's decision (K-109) holds here too.
   ------------------------------------------------------------ */

.rax-update {
    display: flex;
    flex-direction: column;
    gap: var(--sp-6);
    padding: var(--sp-5);
    max-width: 46rem;
}

.rax-update h3 {
    margin: 0 0 var(--sp-3);
    font-size: var(--fs-body);
    font-weight: 600;
    color: var(--c-ink);
}

.rax-update section {
    padding: var(--sp-4);
    border: 1px solid var(--c-line);
    border-radius: var(--r-control);
}

/* Facts in a grid: the label in a fixed column, the value flows. A
   definition list describes exactly this relation and a screen reader
   reads it as pairs too. */
.rax-update-facts {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: var(--sp-2) var(--sp-4);
    margin: 0;
}

.rax-update-facts dt {
    color: var(--c-ink-3);
    font-size: var(--fs-caption);
}

.rax-update-facts dd {
    margin: 0;
    font-size: var(--fs-body);
    overflow-wrap: anywhere;
}

.rax-update-note {
    margin: var(--sp-3) 0 0;
    font-size: var(--fs-caption);
    color: var(--c-ink-3);
}

.rax-update-warning { color: var(--c-neg); }

.rax-update-row {
    display: flex;
    gap: var(--sp-3);
    align-items: center;
    flex-wrap: wrap;
}

.rax-update-path { flex: 1 1 22rem; }

/* ------------------------------------------------------------
   SUPPORT PACKAGE

   The same skeleton as the update screen — both are "about this
   installation" screens and are called from the same drawer. Separate
   classes, because the two may diverge one day and splitting a shared
   class that day costs more than writing two blocks today.
   ------------------------------------------------------------ */

.rax-support {
    display: flex;
    flex-direction: column;
    gap: var(--sp-6);
    padding: var(--sp-5);
    max-width: 46rem;
}

/*  THE SECTION TITLE SPEAKS THE SAME LANGUAGE AS THE FORM'S GROUP LABEL.

    The style was not made up: `.rax-form .rz-fieldset > legend` word for
    word — small, uppercase, finely spaced and a hairline completing the
    rest of the row. Both were bound to this rule so the titles of two
    screens opened from the same drawer (update and support) do not look
    different; no third "panel title" language was born. */
.rax-support h3,
.rax-update h3 {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    margin: 0 0 var(--sp-4);
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    text-transform: uppercase;
    letter-spacing: .04em;
    line-height: var(--lh-tight);
    color: var(--c-ink-3);
}

.rax-support h3::after,
.rax-update h3::after {
    content: "";
    flex: 1 1 auto;
    border-block-start: 1px solid var(--c-line);
}

.rax-support section {
    padding: var(--sp-5);
    border: 1px solid var(--c-line);
    border-radius: var(--r-card);
    background: var(--c-surface);
}

.rax-support-facts {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: var(--sp-3) var(--sp-5);
    margin: 0;
    align-items: baseline;
}

.rax-support-facts dt {
    color: var(--c-ink-3);
    font-size: var(--fs-caption);
}

.rax-support-facts dd {
    margin: 0;
    font-size: var(--fs-body);
    overflow-wrap: anywhere;
}

/* The path and the version are IDENTIFIERS: compared by eye, so
   monospace (tokens.css's own reason). */
.rax-support-facts dd code {
    font-family: var(--font-code);
    font-size: var(--fs-dense);
    color: var(--c-ink-2);
}

.rax-support-note {
    margin: var(--sp-4) 0 0;
    font-size: var(--fs-caption);
    line-height: var(--lh-body);
    color: var(--c-ink-3);
}

/*  THE PACKAGE CONTENTS: no bullets, two columns.

    The left column is the file name (monospace, an identifier), the
    right column what it is. A bulleted list buried the file names inside
    sentences and the eye found which line was which file only by reading. */
.rax-support-list {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: var(--sp-2) var(--sp-5);
    margin: var(--sp-4) 0 0;
    padding: 0;
    list-style: none;
    font-size: var(--fs-caption);
    color: var(--c-ink-3);
}

.rax-support-list dt {
    font-family: var(--font-code);
    font-size: var(--fs-dense);
    color: var(--c-ink-2);
}

.rax-support-list dd { margin: 0; line-height: var(--lh-body); }

/*  A link but it looks like a button: what it does is an action (produce
    and download a file), its target is not a page. The sizes are from
    `.rz-button.rz-primary` — every primary button in the shell is like
    this. */
.rax-support-link {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    margin-block-start: var(--sp-5);
    min-block-size: var(--row-h);
    padding-inline: var(--sp-5);
    border: 1px solid var(--c-accent);
    border-radius: var(--r-control);
    background: var(--c-accent);
    color: var(--c-on-accent);
    font-size: var(--fs-body);
    font-weight: var(--fw-medium);
    text-decoration: none;
    transition: background-color var(--motion) var(--motion-ease),
                border-color     var(--motion) var(--motion-ease);
}

.rax-support-link:hover {
    background: var(--c-accent-2);
    border-color: var(--c-accent-2);
}

.rax-support-link:focus-visible {
    outline: 2px solid var(--c-accent-dk);
    outline-offset: 1px;
}

/* The badge in the drawer: it REPLACES the row's description, it is not
   put next to it. When there is a new version that is the only thing the
   user needs to read. */
.rax-settings-link small.rax-update-badge {
    color: var(--c-accent);
    font-weight: 600;
}

/* ------------------------------------------------------------
   STARTUP SCREENS — setup and problem

   No shell (PlainLayout): the menu, tabs and key facts are not drawn
   because both want the database. What is left is a single card; sizes
   and colours still come from the tokens, so the screen is not bare but
   shell-less.
   ------------------------------------------------------------ */

/*  ITS NAME WAS `rax-plain`, IT COLLIDED (K-160).

    The form's read-only value also carries the `.rax-plain` class (above,
    `min-height: calc(var(--row-h) - 9px)`). Since this rule came LATER in
    the file it overrode that one: every read-only field on the record
    screen got `min-height: 100vh` and the boxes stretched down the height
    of the screen. The user reported it.

    Both deserved the same name — one "unadorned value", the other
    "unadorned page". THIS one was renamed: a single element carries it,
    the other is used by two framework components.

    The rest of the `rax-plain-*` family (head, group, row, bar…) already
    belongs to this page and was not touched. */
.rax-plain-page {
    min-height: 100vh;
    background: var(--c-canvas);
    color: var(--c-ink);

    /* THE FONT FAMILY IS GIVEN HERE and it was added by measuring: these
       two screens have no Radzen component, so no font family carried by
       the `rz-*` classes either. Title, paragraph and list fell to the
       browser's default — Times New Roman. The FIRST screen the customer
       sees is the setup wizard. */
    font-family: var(--font-ui);
}

.rax-plain-head {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-4) var(--sp-5);
    border-block-end: 1px solid var(--c-line);
    background: var(--c-surface);
}

.rax-plain-mark {
    display: grid;
    place-items: center;
    inline-size: 1.75rem;
    block-size: 1.75rem;
    border-radius: var(--r-control);
    background: var(--c-accent);
    color: var(--c-on-accent);
    font-weight: 700;
}

.rax-plain-name { font-weight: 600; letter-spacing: 0.04em; }

.rax-plain-body {
    max-width: 44rem;
    margin-inline: auto;
    padding: var(--sp-6) var(--sp-5) var(--sp-8);
    display: flex;
    flex-direction: column;
    gap: var(--sp-5);
}

.rax-plain-body h1 { margin: 0; font-size: 1.4rem; }
.rax-plain-body h2 { margin: 0 0 var(--sp-3); font-size: var(--fs-body); font-weight: 600; }

.rax-plain-group {
    padding: var(--sp-4);
    border: 1px solid var(--c-line);
    border-radius: var(--r-control);
    background: var(--c-surface);
}

/* The fields flow in a row and drop one under the other on a narrow
   screen: the setup screen must also open on a laptop in the server room. */
.rax-plain-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-4);
    margin-block-end: var(--sp-3);
}

.rax-plain-row > label {
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
    flex: 1 1 14rem;
    font-size: var(--fs-caption);
    color: var(--c-ink-2);
}

.rax-plain-row small { color: var(--c-ink-3); }

.rax-plain-check {
    flex-direction: row !important;
    align-items: center;
    flex: 0 0 auto !important;
}

.rax-plain-note { margin: 0; font-size: var(--fs-caption); color: var(--c-ink-3); }
.rax-plain-ok  { margin: var(--sp-3) 0 0; font-size: var(--fs-caption); color: var(--c-pos); }

/* Setup log: written as the steps arrive. The user must see what is
   happening — a silent wait cannot be told apart from a frozen screen. */
.rax-plain-log {
    margin: 0;
    padding: var(--sp-3);
    border-radius: var(--r-control);
    background: var(--c-canvas);
    border: 1px solid var(--c-line);
    font-size: var(--fs-caption);
    white-space: pre-wrap;
    max-block-size: 16rem;
    overflow-y: auto;
}

.rax-plain-bar {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
}

/* ------------------------------------------------------------
   INPUT AND BUTTON OF THE PLAIN SCREENS

   There are NO Radzen components on the login and logout screens: both
   write a cookie, a cookie wants HttpContext and in an interactive
   circuit the response is long finished (K-124). So the boxes there are
   plain HTML.

   BUT THE LANGUAGE IS THE SAME. The sizes below were not made up, they
   were taken one to one from the shell:

     frame    → `.rax-field`'s frame (--c-field-line, 10%)
     height   → --row-h, the same as a grid row
     type     → --fs-input, the same as the input in a form
     focus    → ONE FRAME: the border turns to the accent, no outline
                (the same rule as `.rax-pagerx-input:focus`)
     button   → the same three lines as `.rz-button.rz-primary`

   No second "form look" was defined; had one been, it would diverge from
   the shell's one day and the user would see two different forms in the
   same product.
   ------------------------------------------------------------ */

/*  THE SCOPE IS ONLY THE LOGIN CARD — and it was narrowed by measuring.

    The rule was first written as `.rax-plain-row input[...]`, i.e. it also
    covered the setup and problem screens. But the boxes there are RADZEN
    components and the measurement showed: it caught those with
    `type="password"` and, since Radzen's own class chain is more
    specific, not the others. The result: two different boxes in the same
    form — 40px/16px next to 40px/14px.

    Painting none beats painting half: the look on those screens is
    Radzen's and should stay so. The boxes here are plain HTML, and we own
    them.

    (That the plain screens get none of the shell's Radzen adjustments is
    a separate gap: those rules live under `.rax-shell`. It stands as a
    debt in the README.) */
.rax-auth-fields input {
    inline-size: 100%;

    /*  THE OUTER SIZE IS THE SAME AS THE SHELL'S FIELD: `.rax-field` carries
        a 1px frame + an input `--row-h` tall, i.e. 36px from outside.
        Without `box-sizing` the browser's own padding is added and, as
        measured, it came out 38px. */
    box-sizing: border-box;
    min-block-size: calc(var(--row-h) + 2px);
    padding-block: 0;
    padding-inline: var(--sp-3);
    font-family: var(--font-ui);
    font-size: var(--fs-input);
    color: var(--c-ink);
    background: transparent;
    border: 1px solid var(--c-field-line);
    border-radius: var(--r-control);
    transition: border-color var(--motion) var(--motion-ease);
}

.rax-auth-fields input::placeholder { color: var(--c-ink-3); }

/*  ONE FRAME. If both an outline and a border are drawn the field has two
    boundaries and focus looks "thickened".

    `box-shadow: none` IS REQUIRED and WAS MISSING HERE (K-162). On focus
    the email box on the login screen drew TWO frames: its own border and
    the global ring in tokens.css
    (`:where(button, input, select, [tabindex]):focus-visible`).
    `outline: none` does not silence that ring — the ring is a
    `box-shadow`, not an `outline`.

    This lesson was ALREADY WRITTEN in the repository (the
    `.rax-pagerx-input:focus` note, with the same sentences) but was not
    applied at this third place. The user sent a screenshot. */
.rax-auth-fields input:focus,
.rax-auth-fields input:focus-visible {
    border-color: var(--c-accent);
    box-shadow: none;
    outline: none;
}

.rax-plain-primary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);

    /* The SAME outer size as the input: in a stacked form a button 2px
       shorter looked misaligned (measured: 34 against 36). */
    box-sizing: border-box;
    min-block-size: calc(var(--row-h) + 2px);
    padding-inline: var(--sp-5);
    font-family: var(--font-ui);
    font-size: var(--fs-body);
    font-weight: var(--fw-medium);
    color: var(--c-on-accent);
    background: var(--c-accent);
    border: 1px solid var(--c-accent);
    border-radius: var(--r-control);
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--motion) var(--motion-ease),
                border-color     var(--motion) var(--motion-ease);
}

.rax-plain-primary:hover {
    background: var(--c-accent-2);
    border-color: var(--c-accent-2);
}

.rax-plain-primary:focus-visible {
    outline: 2px solid var(--c-accent-dk);
    outline-offset: 1px;
}

.rax-plain-warning { color: var(--c-neg); }

/* ------------------------------------------------------------
   LOGIN CARD

   The setup and problem screens are WIDE: a form to fill in, a tenant
   table to read. Login is two fields — two left-aligned boxes inside a
   44rem body looked lost in the middle of the screen.

   The card is flat: no shadow, a border. The whole product is like this
   (tokens.css has no shadow token at all) and the login screen alone
   rising into the air would say it does not belong to the product.
   ------------------------------------------------------------ */

.rax-auth {
    inline-size: 100%;
    max-inline-size: 21rem;
    margin-inline: auto;
    margin-block-start: clamp(var(--sp-5), 7vh, 4rem);
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}

.rax-auth-card {
    display: flex;
    flex-direction: column;
    gap: var(--sp-5);
    padding: var(--sp-6);
    background: var(--c-surface);
    border: 1px solid var(--c-line);
    border-radius: var(--r-card);
}

.rax-auth-head {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

.rax-auth-head h1 {
    margin: 0;
    font-size: var(--fs-page);
    font-weight: var(--fw-medium);
    line-height: var(--lh-tight);
}

.rax-auth-head p {
    margin: 0;
    font-size: var(--fs-caption);
    color: var(--c-ink-3);
    line-height: var(--lh-body);
}

/*  ERROR: A BORDERED STRIP, NOT A FILLED BLOCK.

    The same decision holds everywhere in the product — even the
    destructive button is not filled red (shell.css). A filled red box
    would make a mistyped password look like data loss.

    The background DERIVES from the ink (8%), not a hand-picked pink: it
    follows by itself when the design changes and in the dark theme — the
    same technique as the line tokens. */
.rax-auth-error {
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid color-mix(in srgb, var(--c-neg) 35%, var(--c-canvas));
    border-inline-start: 2px solid var(--c-neg);
    border-radius: var(--r-control);
    background: color-mix(in srgb, var(--c-neg) 8%, var(--c-canvas));
    color: var(--c-ink);
    font-size: var(--fs-body);
    line-height: var(--lh-body);
}

/* The success strip is THE SAME box as the error's — only the colour axis
   differs (K-182). No second notice language was defined: the user sees a
   strip in the same place at the same size and its colour says what it
   is. The background again derives from the ink, following the dark
   theme by itself. */
.rax-auth-ok {
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid color-mix(in srgb, var(--c-pos) 35%, var(--c-canvas));
    border-inline-start: 2px solid var(--c-pos);
    border-radius: var(--r-control);
    background: color-mix(in srgb, var(--c-pos) 8%, var(--c-canvas));
    color: var(--c-ink);
    font-size: var(--fs-body);
    line-height: var(--lh-body);
}

.rax-auth-fields {
    display: flex;
    flex-direction: column;
    gap: var(--form-gap);
}

.rax-auth-fields label {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    font-size: var(--fs-caption);
    color: var(--c-ink-2);
}

/* The button spans the whole card: the card has a single action and
   nothing else to align with. */
.rax-auth .rax-plain-primary { inline-size: 100%; }

.rax-auth-foot {
    margin: 0;
    font-size: var(--fs-caption);
    line-height: var(--lh-body);
    color: var(--c-ink-3);
    text-align: center;
}

/* The link on the bottom line (K-182). The plain screens have no shell, so
   the browser's default blue underlined link appeared and clashed with the
   card's calm language. It takes its colour from the text itself; the
   underline only on hover. */
.rax-auth-foot a {
    color: var(--c-ink-2);
    text-decoration: none;
    border-block-end: 1px solid var(--c-line-2);
}

.rax-auth-foot a:hover,
.rax-auth-foot a:focus-visible {
    color: var(--c-accent);
    border-block-end-color: var(--c-accent);
}

/* The screen's key facts: version and company. The only "where am I" hint
   on the login screen — no shell, no menu. */
.rax-auth-mark {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    font-family: var(--font-code);
    font-size: var(--fs-caption);
    color: var(--c-ink-3);
}

/* The secondary action on a plain screen is a LINK: a file download does
   not go through the Blazor circuit, the browser goes straight to the
   endpoint. The one thing that must work even when the circuit is down. */
.rax-plain-link {
    font-size: var(--fs-caption);
    color: var(--c-accent);
    text-decoration: underline;
    text-underline-offset: 0.2em;
}

.rax-plain-list { margin: 0; padding-inline-start: var(--sp-5); }
.rax-plain-list li { margin-block-end: var(--sp-2); font-size: var(--fs-body); }

.rax-plain-table { width: 100%; border-collapse: collapse; font-size: var(--fs-caption); }
.rax-plain-table th,
.rax-plain-table td {
    text-align: start;
    padding: var(--sp-2);
    border-block-end: 1px solid var(--c-line);
}

/* ----------------------------------------------------------
   PERMISSION MATRIX  (K-181)

   The inside of a modal — NOT A SCREEN. The view type budget does not
   move: this does not replace a `<RadzenDataGrid>`, it collects the
   answer to a question (K-180).

   Why not a grid: there are 70+ rows to choose and the user does not ADD
   them one by one, they tick them group by group. The detail grid's verb
   is "add a row", the verb here is "tick".

   Colour and size from tokens (K-036): the dark theme is not written
   separately, the tokens already turn.
   ---------------------------------------------------------- */

.rax-grant-list {
    /* The height is LIMITED and scrolling is INSIDE: if the modal itself
       grows past the screen the Save button becomes invisible — K-160's
       "box growing to the screen's height" defect. */
    max-height: 46vh;
    overflow-y: auto;
    border: 1px solid var(--c-line);
    border-radius: var(--r-card);
    background: var(--c-surface);
}

.rax-grant-group + .rax-grant-group {
    border-top: 1px solid var(--c-line);
}

.rax-grant-head {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    background: var(--c-surface-2);
    color: var(--c-ink-3);
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    text-transform: uppercase;
    letter-spacing: .04em;

    /* The group title stays in place while scrolling: in the middle of
       seventy rows the question "which screen am I on" must not arise. */
    position: sticky;
    top: 0;
    z-index: 1;
}

/* The menu group, before the screen name and FADED: which menu we are in
   is context, which screen we are on is the title itself (K-210). */
.rax-grant-menu {
    color: var(--c-ink-3);
    opacity: .7;
}

.rax-grant-menu::after {
    content: "›";
    margin-inline: var(--sp-2);
}

.rax-grant-items {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: var(--sp-2) var(--sp-4);
    padding: var(--sp-3) var(--sp-4) var(--sp-4);
}

.rax-grant-item {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    min-width: 0;
    cursor: pointer;
}

.rax-grant-item > span {
    /* A long label does not squash the code, it clips itself. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rax-grant-item > code {
    margin-inline-start: auto;
    font-family: var(--font-code);
    font-size: var(--fs-dense);
    color: var(--c-ink-3);
    white-space: nowrap;
}

/* ----------------------------------------------------------
   DATA PERMISSION SCREEN  (K-210)

   The permission matrix's sibling with the same constraints: inside a
   modal, the view type budget does not move, colour and size from
   tokens.

   The difference is in the number of rows: the matrix has seventy boxes
   ticked group by group, this asks about a screen's fields one by one. So
   not a checkbox but a three-option box — the difference between
   «hidden» and «read-only» cannot be told by a mark being there or not.
   ---------------------------------------------------------- */

.rax-access-fields {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: var(--sp-2) var(--sp-4);

    /* The same reason as the matrix: if the modal overflows the screen
       the Save button becomes invisible (K-160). */
    max-height: 32vh;
    overflow-y: auto;
}

.rax-access-field {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    min-width: 0;
}

.rax-access-field > span {
    /* A long label does not squash the dropdown, it clips itself. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--c-ink-2);
    font-size: var(--fs-caption);
}

/* ============================================================
   DESIGNER — FULL PAGE AND DRAG FEEDBACK (K-186)

   Two changes, both parts of the same problem: the designer was cramped
   in a modal and while dragging nothing said where it would land.
   ============================================================ */

.rax-designer-page {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);

    /* The WHOLE height inside the shell. The canvas scroll chain wants a
       limit to hold on to; left `auto` the page would grow with its
       content and the command strip would go off the bottom of the screen
       (it happened once in K-122). */
    block-size: 100%;
    min-block-size: 0;
    padding: var(--sp-5);

    /* Workbench (K-196): the panes and the canvas sit ON TOP of it. */
    background: var(--c-desk);
}

.rax-designer-head {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-rows: auto auto;
    align-items: center;
    gap: var(--sp-2) var(--sp-4);
    flex: 0 0 auto;
}

/*  THE TITLE NOW COMES FROM A TOKEN (K-191).

    It said `var(--fs-h1, 20px)` and there is NO TOKEN CALLED `--fs-h1` —
    so the value always fell back: 20px. tokens.css's screen title is 18px
    with the note: «screen title. Nothing above it.» The designer shouted
    at a tier no screen of the application has. The rule on the file's
    second line forbids it too: no size other than tokens is defined here. */
.rax-designer-head h1 {
    margin: 0;
    font-size: var(--fs-page);
    font-weight: var(--fw-medium);
    color: var(--c-ink);
}

/*  THE HELP TEXT'S LINE GOT SHORTER.

    Measured: in a 1280px window the paragraph was 898px wide and built
    ~150-character lines at 12px; the eye cannot find the start of the next
    line from the end of one. The limit is given in a measure (`ch`), not
    pixels — when the density tier grows the text the box grows with it. */
.rax-designer-head p {
    grid-column: 2;
    margin: 0;
    max-inline-size: 78ch;
    font-size: var(--fs-caption);
    line-height: var(--lh-body);
    color: var(--c-ink-3);
}

/* The back button. On a full page the answer to "how do I get out of
   here" must stay on screen — there is no modal cross. */
.rax-designer-back {
    grid-row: 1 / span 2;
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-2) var(--sp-4) var(--sp-2) var(--sp-3);
    background: var(--c-surface);
    border: 1px solid var(--c-line);
    border-radius: var(--r-control);
    color: var(--c-ink-2);
    font: inherit;
    font-size: var(--fs-caption);
    cursor: pointer;
}

.rax-designer-back:hover {
    border-color: var(--c-accent);
    color: var(--c-accent);
}

/*  A keyboard user sees where they are too (K-191). The button is a
    `<button>` but the browser's default frame stayed faint with
    `font: inherit` and its own border; the ring comes from the token
    (`--focus-ring`), so the focus language is the same as the rest of the
    application. For a user navigating with Tab this button is the way out
    of the designer. */
.rax-designer-back:focus-visible {
    outline: none;
    border-color: var(--c-accent);
    box-shadow: var(--focus-ring);
}

.rax-designer-back .rzi { font-size: 18px; }

.rax-designer-body {
    flex: 1 1 auto;
    min-block-size: 0;
}

/* On a full page the panes breathe: the 200/230px of the modal choked the
   canvas. */
.rax-designer-page .rax-designer {
    grid-template-columns: 240px minmax(0, 1fr) 280px;
}

/* ------------------------------------------------------------
   DRAG STATE

   JS does the highlighting (rax.js) and NEVER TOUCHES THE CIRCUIT; the
   rules here only draw the classes it writes.
   ------------------------------------------------------------ */

.rax-designer-chip:active,
.rax-design-slot:active { cursor: grabbing; }

/* When dragging starts the droppable places show themselves: the canvas
   stays calm but the targets become selectable. */
.rax-designer.dragging .rax-design-slot {
    border-color: var(--c-line);
}

/* TARGET LINE — «it will land here».
   An overlay, NOT a border: with a border the slot would grow 2px and
   everything below it would move a pixel; a list trembling throughout the
   drag would draw more attention than the mark itself. */
.rax-design-slot.rax-target,
.rax-design-tail.rax-target {
    position: relative;
    border-color: var(--c-accent);
    background: var(--c-accent-bg);
}

.rax-design-slot.rax-target::before,
.rax-design-tail.rax-target::before {
    content: "";
    position: absolute;
    inset-inline: -2px;
    inset-block-start: -2px;
    block-size: 2px;
    background: var(--c-accent);
    border-radius: 2px;
}

/*  THE ENTITY DESIGNER'S CANVAS IS A TARGET TOO — AND IT WAS SILENT (K-191).

    .rax-studio-canvas was in rax.js's target list from the very start
    (K-189: «an empty canvas is a target too») but there was no rule for
    it. Measured — the class was put on by hand and read:

        without rax-target → white background, grey border
        with rax-target    → white background, grey border   (exactly the same)

    So the user stood on a valid target and the screen did not say so.
    K-186's own sentence: «while dragging nothing SAID where it would
    land» — closed there for the slots, the canvas was skipped here.

    The counterpart of the slot line (::before) is NOT here, on purpose:
    the line means «above this row», while the canvas is not a single place
    but the whole surface. Since it says something different its mark is
    different too — background and border.

    THE LAYOUT DESIGNER'S CANVAS IS OUTSIDE THIS RULE. In the first version
    it was put in the selector too and the measurement showed it was dead:
    `.rax-designer-canvas` is NOT in the target list — there the targets
    are the slots and the tail themselves. A rule with zero consumers does
    not stay in this repository (K-169); adding it to the list would be
    highlighting a target that does nothing. */
.rax-studio-canvas.rax-target {
    border-color: var(--c-accent);
    background: var(--c-accent-bg);
}

/* The toolbox is a target too: a field is dragged there to remove it from
   the form and it must say so. */
.rax-designer-tools.rax-target {
    border-color: var(--c-accent);
    background: var(--c-accent-bg);
}

/* ------------------------------------------------------------
   EMPTY CANVAS: NOT TEXT, AN INVITATION (K-191)

   In the entity designer with no fields the canvas was an empty 639×563
   surface with a single thing in it: a 621×17 grey sentence at the top
   left corner. Measured. Yet the WHOLE surface is a drop target (K-189) —
   the screen said so nowhere.

   The dashed frame is not a made-up language: the «drop at the end of the
   section» tail (`.rax-design-tail`) says the same thing the same way. The
   difference is that this one stays BEFORE dragging starts too — because
   there is nothing else to show on this screen, so unlike the tail box it
   is not an invitation with nothing behind it.
   ------------------------------------------------------------ */

.rax-designer-drop {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--sp-3);
    min-block-size: 100%;
    padding: var(--sp-6);
    border: 1px dashed var(--c-line-2);
    border-radius: var(--r-card);
    text-align: center;
    font-size: var(--fs-caption);
    line-height: var(--lh-body);
    color: var(--c-ink-3);
}

.rax-designer-drop .rax-empty-icon { font-size: 32px; }

/* When dragging starts the invitation turns to the accent too: at the
   same time and in the same colour as the canvas's own highlight (the
   `.rax-target` above) — not two separate marks but two layers of one mark.

   Only `.rax-studio`: this box exists on the entity designer's empty
   canvas and has no counterpart in the layout designer. Writing both roots
   would be styling an element that does not exist. */
.rax-studio.dragging .rax-designer-drop {
    border-color: var(--c-accent);
    color: var(--c-accent);
}

/* ------------------------------------------------------------
   THE PROPERTIES PANEL'S EMPTY STATE

   The sentence «Düzenlemek için kanvastan bir alan seçin» was a 17px grey
   line at the top left corner of the 280px pane; the rest of the pane was
   pointless empty space.

   NO NEW EMPTY-STATE LANGUAGE WAS WRITTEN: the repository already has one
   and its only consumer was the work area (`.rax-empty`, RaxWorkspace).
   This is the second consumer. The sizes are cut down to the pane — a
   44px icon in a 218px pane would be a poster, not a page.
   ------------------------------------------------------------ */

.rax-designer-props .rax-empty,
.rax-studio-props .rax-empty {
    padding: var(--sp-6) var(--sp-2);
    gap: var(--sp-3);
    text-align: center;
    font-size: var(--fs-caption);
    line-height: var(--lh-body);
}

.rax-designer-props .rax-empty-icon,
.rax-studio-props .rax-empty-icon { font-size: 28px; }

/* Order buttons — the keyboard twin of dragging (K-186). */
.rax-designer-order {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin-block-start: var(--sp-4);
}

.rax-designer-order .label {
    flex: 1 1 auto;
    font-size: var(--fs-caption);
    color: var(--c-ink-3);
}

.rax-designer-order .position {
    font-family: var(--font-code);
    font-size: var(--fs-dense);
    color: var(--c-ink-3);
}

/* ============================================================
   CONTROL PALETTE (K-187)

   The top half of the toolbox. The bottom half (fields removed from the
   form) is drawn with `.rax-designer-chip` and that language DID NOT
   CHANGE — both are dragged, both land in the same place; the difference
   is not in the look but in what they do.
   ============================================================ */

/*  THE PALETTE IS NO LONGER A GRID BUT A LIST (K-192).

    They were two columns of square boxes and each box held an icon and the
    control's NAME. The user's sentence: «show the controls on the left
    like the controls that appear on the right; do not write Tarih saat at
    the start, write it inside the edit, let it be understood from the
    format; not square but more horizontal like the control on screen».

    A fair objection: a square icon box looked NOTHING like what would be
    born when dragged. What appears on the canvas is a horizontal field;
    that is what should sit in the palette too. Now every row is a
    miniature of a field — handle + frame + sample value. */
.rax-designer-palette {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    margin-block-end: var(--sp-5);
}

/* The row is the mould of the slot on the canvas: the handle on the left,
   the field on the right. `.rax-design-slot` does exactly this — there the
   handle is absolutely positioned because it must not break the real
   form's grid, here there is no grid, so plain flex. */
.rax-designer-control {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-1);
    border: 1px solid transparent;
    border-radius: var(--r-control);
    line-height: var(--lh-tight);
    color: var(--c-ink);
    cursor: grab;

    /*  The transition is written WITH A DURATION (K-191). Measured: the
        computed `transition` value was "all", i.e. a duration of 0 —
        nothing transitioned. The token already existed and was unused. */
    transition: background-color var(--motion) var(--motion-ease),
                border-color     var(--motion) var(--motion-ease);
}

/*  ON HOVER THE ROW LIGHTS UP, not the box.

    The box itself imitates a field frame; painting it with the accent
    background would say «this field is selected» and nothing is selected.
    The highlight is on the row itself — the same language and the same
    two values as `.rax-design-slot:hover` on the canvas. */
.rax-designer-control:hover {
    border-color: var(--c-line-2);
    background: var(--c-surface);
}

.rax-designer-control:active { cursor: grabbing; }

/*  The handle is born as quiet as on the canvas and goes to full ink when
    hovering over the row (K-191). */
.rax-control-grip {
    display: flex;
    flex: none;
    opacity: .38;
    transition: opacity var(--motion) var(--motion-ease);
}

.rax-designer-control:hover .rax-control-grip { opacity: 1; }

.rax-control-grip .rzi {
    font-size: 16px;
    color: var(--c-ink-3);
}

/*  FAKE EDITOR — sizes from the real field frame.

    Corner `--r-control`, horizontal padding `--sp-3`, type `--fs-table`,
    height `--row-h`: all four were read from `.rax-field` and the rule of
    the input inside it, not guessed. No background — the real field has
    none either (K-087).

    THE BORDER IS NOT `--c-field-line` BUT `SOFT` — AND THIS WAS MEASURED.
    First `--c-field-line` (10%) was written; the real field on the canvas
    measured 6%:

        field on the canvas → color(srgb 0.9164 …)   (--c-field-line-soft)
        palette box         → color(srgb 0.8816 …)   (--c-field-line)

    The cause is `.rax-field:has(:disabled)`: in design mode inputs are
    disabled, because a click SELECTS, it does not enter data. So the lines
    of two boxes side by side diverged by one tier. The palette follows its
    neighbour — and that is also what is right: the box in the palette is
    not a writable field either. */
.rax-control-box {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    min-block-size: var(--row-h);
    padding-inline: var(--sp-3);
    border: 1px solid var(--c-field-line-soft);
    border-radius: var(--r-control);
    font-size: var(--fs-table);
    color: var(--c-ink);
}

/* On hover the line goes up to the WRITABLE field's weight (6% → 10%): not
   a made-up highlight but one tier up in the same family. */
.rax-designer-control:hover .rax-control-box { border-color: var(--c-field-line); }

.rax-control-box .value {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* A dropdown's empty state is faint in reality too: it shows not a value
   but its invitation. */
.rax-control-box .value.faint { color: var(--c-ink-3); }

.rax-control-box .rzi {
    flex: none;
    font-size: 16px;
    color: var(--c-ink-3);
}

/*  THE NUMBER IS RIGHT-ALIGNED AND TABULAR — the same as the real number
    input (K-051, `--num-align`/`--num-variant`). `1.112,45` in the palette
    and `1.112,45` in the form stand at the same alignment with the same
    digit width; that is what says it is a decimal. */
.rax-control-box.number .value {
    text-align: var(--num-align);
    font-variant-numeric: var(--num-variant);
}

/*  «Not»'s only difference is its height and that difference is real: the
    generated field is born multi-line too. The line break in the sample
    text is kept (`pre-line`), otherwise the two-line sample would line up
    on one line and the difference would not show. */
.rax-control-box.note {
    align-items: flex-start;
    min-block-size: calc(var(--row-h) * 1.6);
    padding-block: var(--sp-2);
}

.rax-control-box.note .value {
    white-space: pre-line;
    overflow: hidden;
    line-height: var(--lh-body);
}

/*  THE CHECKBOX HAS NO FRAME.

    The real form has none either: a check box is its own box, drawing a
    second frame around it would show two nested boxes. The row height
    stays the same as the others so the list does not jump. */
.rax-control-box.check {
    border-color: transparent;
    padding-inline: var(--sp-2);
}

.rax-control-box.check .rzi {
    font-size: 18px;
    color: var(--c-accent);
}

/* ------------------------------------------------------------
   SETTINGS OF THE ADDED FIELD
   ------------------------------------------------------------ */

.rax-designer-settings {
    margin-block-start: var(--sp-4);
    padding-block-start: var(--sp-4);
    border-block-start: 1px solid var(--c-line);
}

.rax-designer-settings h4 {
    margin: 0 0 var(--sp-2);
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--c-ink-3);
}

.rax-designer-settings code {
    font-family: var(--font-code);
    font-size: var(--fs-dense);
    color: var(--c-ink-2);
}

/* The two small titles in the entity designer's left pane: palette
   (K-189) and scope (K-193). In the layout designer section titles are
   `h3` and already styled; here the left panel has its own language, so
   it is bound to it without writing the same sizes again. */
.rax-studio-palette-title,
.rax-studio-scope-title {
    margin: 0 0 var(--sp-3);
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--c-ink-3);
}

/*  THE TOP MARGIN IS TAKEN BACK WITH SPECIFICITY — learned by measuring.

    The palette title came with `margin: var(--sp-5) 0 …` and K-191's
    sticky title rule (`.rax-studio-fields h3`, 0,1,1) beat it: the class
    selector (0,1,0) is weaker, so the top margin turned into minus the
    padding and the title stuck to the button above it. The distinction is
    given here, with its own specificity.

    The scope title has NO such margin and should not: it is the pane's
    first element, there is nothing above it to set apart from. */
.rax-studio-fields h3.rax-studio-palette-title {
    margin-block-start: var(--sp-5);
}

/* ============================================================
   THE DESIGNER IN A NARROW WINDOW (K-190)

   Three columns mean two FIXED-width side panes + a flexing canvas:
   240 + 280 = 520px goes to the side panes. In a 646px window the canvas
   gets 90px and, measured, the drop target shrinks to a strip and
   dragging does not hold.

   The threshold is 1100px: below it, STACKED. The canvas takes the full
   width, the toolbox and properties panel sit above/below it. Dragging
   works vertically too — the palette and the canvas are still on the same
   screen.
   ============================================================ */

@media (max-width: 1100px) {
    /* THE SELECTOR IS WRITTEN TWICE and it is needed — learned by measuring.
       A media query ADDS NO SPECIFICITY: `.rax-designer-page .rax-designer`
       (0,2,0) written for the full-page shell beat the bare `.rax-designer`
       (0,1,0) here. Measurement:

           grid-template-columns → "240px 70px 280px"
           grid-template-rows    → "101px 320px 0px 0px"

       so the rows applied, the columns did not and the canvas dropped to
       70 pixels. K-062's lesson: a rule being written does not mean it is
       applied. */
    .rax-designer,
    .rax-designer-page .rax-designer {
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: auto minmax(320px, 1fr) auto auto;
    }

    /* IN NARROW MODE THE PAGE SCROLLS, THE PANES ARE NOT SQUASHED.

       Stacked, the four panes do not fit on the screen at once and
       `height: 100%` squeezed them — measured, the toolbox was left just
       tall enough to show its title (~40px). The height is set free: the
       canvas takes its own height, the rest scrolls with the page. In wide
       mode the scroll chain stays AS IT IS. */
    .rax-designer-page { block-size: auto; }

    .rax-designer {
        block-size: auto;
        min-block-size: 0;
    }

    /*  In a narrow window the palette wraps horizontally: so it does not
        eat room vertically, horizontally it already has the full width.

        AFTER K-192 FLEX, NOT A GRID. At one time
        `grid-template-columns: repeat(auto-fill, minmax(96px,1fr))` was
        written here and it DIED when the palette became a list — a grid
        rule does nothing in a flex container. Wrapping is written in
        flex's own language; the lower bound is 200px, not 96px, because
        the row is no longer an icon but a field with its sample value. */
    .rax-designer-palette {
        flex-direction: row;
        flex-wrap: wrap;
    }

    .rax-designer-palette > .rax-designer-control {
        flex: 1 1 200px;
        min-width: 0;
    }

    .rax-designer-tools,
    .rax-designer-props { overflow: visible; }
}

/* The entity designer folds at the same threshold too — same reason, same
   number. At separate thresholds one would fold while the other was
   squeezed and the user would not find why. */
@media (max-width: 1100px) {
    .rax-studio {
        grid-template-columns: minmax(0, 1fr);

        /* The rows are given again too: in one column five children
           (header · fields · canvas · properties · strip) stack and the
           flexing row must be the CANVAS. Otherwise `1fr` would go to the
           field list and the preview would be squashed again. */
        grid-template-rows: auto auto minmax(320px, 1fr) auto auto;

        /* THE SAME reason as in the layout designer: the four panes do not
           fit on the screen at once and `height: 100%` squeezed them — the
           left panel was left just tall enough to show its title. The
           height is free, the rest scrolls with the page. */
        block-size: auto;
        min-block-size: 0;
    }

    .rax-studio > aside,
    .rax-studio > main { overflow: visible; }
}

/* ============================================================
   KANBAN BOARD (K-217)

   No new colour, shadow or rounding was INVENTED: the surface, line, ink
   and accent tokens are shared with the list. The board is not a theme
   but another arrangement of the same theme — with a separate token set
   the dark theme would need separate maintenance in two places (K-117).

   THE ONLY THING SCROLLING HORIZONTALLY IS THE COLUMN STRIP. The body
   does not scroll; the scroll chain set up in K-061 holds on the board too
   — the column titles stay in place, the cards scroll inside themselves.
   ============================================================ */
.rax-board {
    display: flex;
    gap: .75rem;
    align-items: flex-start;
    overflow-x: auto;
    overflow-y: hidden;
    padding-block: .5rem;
    min-block-size: 0;
    flex: 1 1 auto;
}

.rax-board-col {
    display: flex;
    flex-direction: column;
    flex: 0 0 17rem;
    max-block-size: 100%;
    background: var(--c-surface-2);
    border: 1px solid var(--c-line);
    border-radius: .5rem;
    min-block-size: 0;
}

/* Drop target. Marked with `data-over`, the class is not changed: the
   state is an ATTRIBUTE, not an identity. */
.rax-board-col[data-over="1"] {
    border-color: var(--c-accent);
    background: var(--c-accent-bg);
}

.rax-board-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .5rem .625rem;
    border-block-end: 1px solid var(--c-line-2);
}

.rax-board-title {
    font-weight: 600;
    color: var(--c-ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The column's REAL total, not the number of loaded cards: so the «Daha
   fazla» button can say how many are left. */
.rax-board-count {
    flex: 0 0 auto;
    min-inline-size: 1.5rem;
    text-align: center;
    padding: .0625rem .375rem;
    border-radius: 1rem;
    background: var(--c-line);
    color: var(--c-ink-2);
    font-size: .75rem;
}

.rax-board-cards {
    display: flex;
    flex-direction: column;
    gap: .5rem;
    padding: .5rem;
    overflow-y: auto;
    min-block-size: 0;
}

.rax-board-card {
    background: var(--c-surface);
    border: 1px solid var(--c-line-2);
    border-radius: .375rem;
    padding: .5rem .625rem;
    cursor: grab;
}

.rax-board-card:hover { border-color: var(--c-accent); }

/* While saving the card fades: the move goes through the command path
   and until the answer arrives the user must see that SOMETHING is
   happening. */
.rax-board-card[data-busy="1"] {
    opacity: .5;
    cursor: progress;
}

.rax-board-card-title {
    font-weight: 600;
    color: var(--c-ink);
    margin-block-end: .25rem;
}

.rax-board-card-line {
    display: flex;
    justify-content: space-between;
    gap: .5rem;
    font-size: .8125rem;
}

.rax-board-card-label { color: var(--c-ink-3); }
.rax-board-card-value { color: var(--c-ink-2); }

/* An empty column shows a DASH, not nothing: a column of zero height
   would also disappear as a drop target. */
.rax-board-empty {
    color: var(--c-ink-3);
    text-align: center;
    padding-block: .75rem;
}

.rax-board-more {
    background: none;
    border: 1px dashed var(--c-line-2);
    border-radius: .375rem;
    color: var(--c-ink-2);
    padding: .375rem;
    cursor: pointer;
}

.rax-board-more:hover {
    border-color: var(--c-accent);
    color: var(--c-accent);
}

/* ============================================================
   CROSS TABLE (K-218)

   The same reason as the board: no new colour was invented, the tokens are
   shared with the list. The difference is only in structure — here there
   are margin totals and they must be set apart from the body.

   STICKY HEADER AND FIRST COLUMN: in a cross table the eye follows two
   axes at once. Losing which row you are on while scrolling makes the
   table unreadable.
   ============================================================ */
.rax-pivot {
    overflow: auto;
    min-block-size: 0;
    flex: 1 1 auto;
}

.rax-pivot-table {
    border-collapse: collapse;
    inline-size: max-content;
    min-inline-size: 100%;
    font-variant-numeric: tabular-nums;
}

.rax-pivot-table th,
.rax-pivot-table td {
    border: 1px solid var(--c-line);
    padding: .375rem .625rem;
    white-space: nowrap;
}

.rax-pivot-corner,
.rax-pivot-colhead {
    position: sticky;
    inset-block-start: 0;
    z-index: 2;
    background: var(--c-surface-2);
    color: var(--c-ink);
    text-align: start;
}

.rax-pivot-corner {
    inset-inline-start: 0;
    z-index: 3;
}

.rax-pivot-rowhead {
    position: sticky;
    inset-inline-start: 0;
    z-index: 1;
    background: var(--c-surface-2);
    color: var(--c-ink);
    text-align: start;
    font-weight: 500;
}

.rax-pivot-cell {
    text-align: end;
    background: var(--c-surface);
    color: var(--c-ink-2);
}

/* Margin totals are SET APART from the body: a total standing in line is
   taken for a cell of the row. */
.rax-pivot-total {
    text-align: end;
    background: var(--c-surface-2);
    color: var(--c-ink);
    font-weight: 600;
}

.rax-pivot-empty {
    color: var(--c-ink-3);
    text-align: center;
    padding: 2rem;
}

/* ============================================================
   TREE LIST (K-219)

   The same reason as the board and the cross table: no new colour was
   invented. The difference is structural — here there is INDENTATION and
   it is a space inside a cell, not a layout: all rows sit in the same
   table so the side columns stay aligned.
   ============================================================ */
.rax-tree {
    overflow: auto;
    min-block-size: 0;
    flex: 1 1 auto;
}

.rax-tree-table {
    border-collapse: collapse;
    inline-size: 100%;
}

.rax-tree-table th,
.rax-tree-table td {
    border-block-end: 1px solid var(--c-line);
    padding: .3125rem .625rem;
    text-align: start;
    white-space: nowrap;
}

.rax-tree-namehead,
.rax-tree-colhead {
    position: sticky;
    inset-block-start: 0;
    z-index: 1;
    background: var(--c-surface-2);
    color: var(--c-ink);
}

.rax-tree-row { cursor: default; }
.rax-tree-row:hover { background: var(--c-touch); }

.rax-tree-row[data-selected="1"] {
    background: var(--c-accent-bg);
}

.rax-tree-name {
    display: flex;
    align-items: center;
    gap: .25rem;
    inline-size: 100%;
}

/* The indent width is computed inline (depth × 1.25rem): the depth comes
   from the data and CSS cannot know it. */
.rax-tree-indent { flex: 0 0 auto; }

.rax-tree-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 1.5rem;
    block-size: 1.5rem;
    flex: 0 0 auto;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    color: var(--c-ink-3);
}

.rax-tree-toggle:hover { color: var(--c-accent); }

/* A leaf has NO arrow but it has its PLACE: without it the leaf rows'
   names would shift a notch left and nodes at the same level would look
   misaligned. */
.rax-tree-leaf {
    inline-size: 1.5rem;
    flex: 0 0 auto;
}

.rax-tree-label { color: var(--c-ink); }

.rax-tree-cell { color: var(--c-ink-2); }

.rax-tree-empty {
    color: var(--c-ink-3);
    text-align: center;
    padding: 2rem;
}

/* ============================================================
   WHERE THE LABEL GOES — THE FOURTH VIEW AXIS (K-227)

   Three layouts, one markup. `data-label` is on the root element; when it
   is not written at all (or is 'cerceve') the rules above apply and the
   screen stays AS IT IS TODAY — opening a new axis is not changing the
   screen of a user who has made no choice.

   THE MECHANISM IS THE SAME IN BOTH MODES: the `<legend>` leaves the flow.
   The browser opens the notch in the border only for the "rendered
   legend", which is the fieldset's first legend IN THE FLOW. A positioned
   legend is not in the flow — the notch closes by itself, the border is
   drawn unbroken on all four sides. No fake background, no second
   element, no JS measurement (measured in K-221 and it held).

   THESE RULES USED TO BELONG TO THE «FERAH» DESIGN and were TAKEN from
   there. Leaving two authors would mean the same layout coming from the
   design in one place and from the user in another; which one won would
   be left to selector specificity. Ferah's identity stays in its palette.
   ============================================================ */

/*  ON TOP.

    ALIGNED TO THE FRAME, NOT THE VALUE. While the label was in the notch it
    was INSIDE the box and had to start at the same left edge as the value
    (the measured 2px rule above). Once outside, what it is tied to
    changes: now it aligns with the box ITSELF, so in a form the labels and
    frames give one left edge. `-1px` takes back the border width — the
    reference of an absolute position is the padding box, not the outside
    of the frame.

    MAKING ROOM IS THE FIELD'S OWN JOB: since the label left the flow it
    adds nothing to the height, the field's top margin gives the space. The
    grid's row gap (`--form-gap`) is not touched — that space belongs
    between two fields, not to the label. */
[data-label='ust'] .rax-field {
    position: relative;
    margin-block-start: calc(var(--fs-caption) + var(--sp-2));
}

[data-label='ust'] .rax-field > legend {
    position: absolute;
    inset-block-end: calc(100% + var(--sp-2));
    inset-inline-start: -1px;
    padding-inline: 0;
    margin-inline-start: 0;
}

/*  ON THE LEFT.

    The classic corporate form: going down, the eye scans the values in
    one column, the labels stand in a second column.

    THE WIDTH IS A TOKEN, BECAUSE BOTH SIDES READ IT: the field its own
    left padding, the label its own width. Without one number a long label
    would overlap the value and nobody would notice.

    THE LABEL IS OUTSIDE THE FRAME — the same decision as the «on top»
    mode. There too the label leaves the box; leaving it inside would put
    the two layouts into different classes (one part of the box, the other
    its neighbour) and on the same screen both would read as «label».

    THE LABEL IS CENTRED VERTICALLY. The field is as tall as its input;
    aligning the label to the top would leave it hanging high in a
    single-line field. In multi-line fields (description) centring still
    reads right because the label belongs to the whole box, not its first
    line.

    HORIZONTALLY IT LEANS LEFT, not towards the box. Right-aligning glues
    the label to the input and two labels of different lengths start at two
    different places — the LEFT edge the eye reads going down is lost.
    Left-aligned, the labels form one column and the boxes one column: two
    straight edges. The variable gap between them is quiet, not a
    misalignment.

    OVERFLOW IS CLIPPED and that is a deliberate loss: a long label at a
    fixed width is either clipped or wraps. Wrapping changes the row height
    and breaks alignment with the neighbouring field in the grid — clipping
    is visible, misalignment is sneaky. */
[data-label='sol'] .rax-field {
    position: relative;
    margin-inline-start: var(--label-w, 9rem);
}

[data-label='sol'] .rax-field > legend {
    position: absolute;
    inset-inline-end: calc(100% + var(--sp-2));
    inset-block-start: 50%;
    transform: translateY(-50%);
    width: calc(var(--label-w, 9rem) - var(--sp-2));
    padding-inline: 0;
    margin-inline-start: 0;
    text-align: start;
}

/*  THE SECTION TITLE IS ALIGNED IN LEFT MODE TOO.

    When the fields move left, if the section title (`fieldset > legend`,
    i.e. the form's own title) stayed in place two different left edges
    would be born. The title is pulled to the same edge as the values. */
[data-label='sol'] .rax-form .rz-fieldset-content > .rz-row {
    --label-w: 9rem;
}

/*  IN LEFT MODE A GAP OPENS BETWEEN COLUMNS (K-227 addendum).

    In a multi-column form the second column's LABEL started right at the
    foot of the first column's BOX (measured: 6px). The eye reads it not as
    the next field's name but as a note belonging to the box on the left —
    and since the label leans left that reading is even stronger.

    The first column is not affected: to its left is the form's own edge.

    THE FIX USES THE VARIABLE, NOT `gap` — the same reason as the rule
    above: Radzen derives the column size from `--rz-gap`
    (`calc(25% - gap*3/4)`). Writing only `gap`, the fourth field would drop
    to the next row. Measured: with the variable 6px→28px the column went
    289px→273px and the NUMBER OF ROWS DID NOT CHANGE.

    `--rz-row-gap` IS NOT TOUCHED: the vertical space belongs between two
    fields and there is no confusion there.

    The unit is `rem`, because it must scale with density — the same
    decision as `--label-w`. In the compact tier (13px root) 19.5px; in the
    wide tier (16px) 24px. */
[data-label='sol'] .rax-form .rz-fieldset-content > .rz-row {
    --rz-gap: 1.5rem;
}

/* ============================================================
   NOTICE DIALOG (K-230)

   The ONE surface for everything the screen says to the user. Before
   there were four separate surfaces: a toast at the top right, a band at
   the top of the form, Radzen's own confirm dialog and, depending on the
   place, raw exception text.

   IN THE MIDDLE, because what is said stops the work being done at that
   moment. The toast at the top right vanished unread; the band at the top
   of the form was never visible to a user in the middle of a long form.

   A field error is NOT ON THIS SURFACE and must not be: it points at a
   field and its place is under the field. The dialog tells the RECORD'S
   result.
   ============================================================ */

/*  The scrim covers the whole screen and CENTRES the dialog.

    `z-index` is above the shell's highest (140, the menu panel): a notice
    must leave nothing that could cover it — an error message half under
    the menu cannot be read. */
.rax-notice-scrim {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: grid;
    place-items: center;
    padding: var(--sp-5);
    background: var(--c-scrim);
    animation: rax-scrim-in var(--motion-panel) var(--motion-ease) both;
}

/*  The width follows the content but HAS A CEILING: a one-sentence warning
    does not cut across the screen, a three-item error list is not squeezed. */
.rax-notice {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--sp-2) var(--sp-4);

    /*  This repository has NO global `box-sizing` reset (shell.css's
        note): without it padding and border go ON TOP of 100% and on a
        narrow screen the dialog overflows the scrim. Measured: in a 408px
        window the box came out 410px. */
    box-sizing: border-box;
    inline-size: min(34rem, 100%);
    padding: var(--sp-5);
    background: var(--c-surface);
    border: 1px solid var(--c-line);
    border-radius: var(--r-panel, var(--r-control));
    box-shadow: var(--sh-3);
    animation: rax-dialog-in var(--motion-panel) var(--motion-ease);
}

/*  THE ICON TELLS THE KIND, THE COLOUR THE SEVERITY.

    All four colours are tokens: error and warning are the signal colours
    already used in the table (`--c-neg`, `--c-flag`), success is the
    balance's positive (`--c-pos`), info and question the identity colour
    (`--c-accent`). No new colour was INVENTED — five notice kinds, zero new
    tokens. */
.rax-notice-icon {
    font-family: 'Material Symbols', 'Material Icons';
    font-size: calc(var(--fs-table) + 10px);
    line-height: 1;
    color: var(--c-accent);
}

.rax-notice[data-kind='error']   .rax-notice-icon { color: var(--c-neg); }
.rax-notice[data-kind='warning']  .rax-notice-icon { color: var(--c-flag); }
.rax-notice[data-kind='success'] .rax-notice-icon { color: var(--c-pos); }

.rax-notice-body {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    min-inline-size: 0;
}

.rax-notice-title {
    margin: 0;
    font-size: var(--fs-section);
    font-weight: var(--fw-medium);
    line-height: var(--lh-tight);
    color: var(--c-ink);
}

.rax-notice-text {
    margin: 0;
    font-size: var(--fs-table);
    line-height: var(--lh-body);
    color: var(--c-ink-2);
    overflow-wrap: anywhere;
}

/*  Items: a save can reject several rules at once and instead of stopping
    the user three times, all three are in the same dialog. */
.rax-notice-list {
    margin: 0;
    padding-inline-start: var(--sp-5);
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
    font-size: var(--fs-table);
    line-height: var(--lh-body);
    color: var(--c-ink);
}

/*  The strip is in the second column: the space under the icon stays
    empty and the buttons start at the same line as the text. */
.rax-notice-strip {
    grid-column: 2;
    display: flex;
    justify-content: flex-end;
    gap: var(--sp-2);
    margin-block-start: var(--sp-2);
}

/*  The button speaks the shell's language but is NOT tied to Radzen: this
    component manages focus (it focuses the confirm button when opened) and
    a Radzen button's element reference is closed to the outside. */
.rax-notice-button {
    min-block-size: var(--row-h);
    padding-inline: var(--btn-px);
    font: inherit;
    font-size: var(--fs-table);
    color: var(--c-ink);
    background: var(--c-surface-2);
    border: 1px solid var(--c-line-2);
    border-radius: var(--r-control);
    cursor: pointer;
    transition: background var(--motion) var(--motion-ease);
}

.rax-notice-button:hover { background: var(--c-touch, var(--c-surface-2)); }

.rax-notice-confirm {
    color: var(--c-on-accent);
    background: var(--c-accent);
    border-color: var(--c-accent);
}

.rax-notice-confirm:hover { filter: brightness(1.08); }

/*  ON AN ERROR THE CONFIRM BUTTON IS IN THE IDENTITY COLOUR TOO. A red
    button was tried and dropped: the icon is already red, with a red
    button too the dialog says «you are about to destroy something» — yet
    all it will do is close. Severity in the icon, action in the button. */


/* ============================================================
   SKELETON — THE SHAPE OF THE COMING SCREEN (K-238)

   Until the list and form definitions arrived a single ring spun in the
   middle of an empty area. The skeleton draws the shape of the coming
   screen and when the data arrives nothing shifts — measured pixel by
   pixel (x, y, height) in the compact, default and wide tiers.

   THE LIST with its own classes, sizes from the grid's tokens. THE FORM
   is drawn with the form's OWN classes (`rax-form-bar`, `rax-field`,
   `rax-plain`); only the placeholder blocks are here.

   The 150 ms DELAY is deliberate: on a fast load a skeleton flashing for
   one frame and vanishing is a flicker worse than the ring.

   The colours are the two tiers of the field line (`--c-field-line-soft` →
   `--c-field-line`): no new token, right in the dark theme by itself.
   ============================================================ */
.rax-skel {
    overflow: hidden;
    animation: rax-skel-in var(--motion-screen) var(--motion-ease) 150ms both;
}

.rax-skel-list {
    display: flex;
    flex-direction: column;
    /* The list stack's gap is 0 and its content starts 1 px inside (measured). */
    gap: 0;
    padding: 1px 1px 0;
    height: 100%;
    /* THE SAME container name as the real list: on a narrow screen the
       skeleton turns into a card too, at the same threshold (K-242). */
    container: rax-list / inline-size;
}

.rax-skel-bar {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    min-height: var(--bar-h);
    border-bottom: 1px solid var(--c-field-line);
    padding-inline: var(--pad);
}

.rax-skel-grid {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.rax-skel-row {
    display: grid;
    grid-template-columns: 34px 1.2fr 2.4fr 1fr 1fr 1.4fr 1fr;
    align-items: center;
    /* A real row: `--row-h` + the 1 px line below (measured: 26 → 27).
       IT DOES NOT SHRINK: a row that does not fit is cut, not shrunk — in
       wide density twelve rows went down to 36 pixels instead of 43
       (measured). */
    flex: none;
    height: calc(var(--row-h) + 1px);
    padding-inline-end: var(--cell-px);
    border-bottom: 1px solid var(--c-field-line-soft);
}

/* The first column is the place of the selection box: in the real grid too. */
.rax-skel-row::before {
    content: "";
    justify-self: center;
    width: 14px;
    height: 14px;
    border-radius: 3px;
    border: 1px solid var(--c-field-line);
}

.rax-skel-head {
    /* The header has its own token: `--header-h` + 1 (24→25, 32→33, 38→39).
       «`--row-h` − 1» held only in the compact tier BY COINCIDENCE. */
    height: calc(var(--header-h) + 1px);
    border-bottom: 0;
    background: var(--rz-grid-header-background-color);
}

/* All the blocks: the same padding, the same sweep. */
.rax-skel-block {
    display: inline-block;
    vertical-align: middle;
    border-radius: var(--r-control);
    background: linear-gradient(90deg,
        var(--c-field-line-soft) 25%,
        var(--c-field-line) 50%,
        var(--c-field-line-soft) 75%) 0 0 / 400% 100%;
    animation: rax-skel-sweep 1.6s ease-in-out infinite;
}

/* Button place: the real button is `--row-h` tall (frame included). */
.rax-skel-pill  { flex: none; width: 76px; height: var(--row-h); }
.rax-skel-pill:first-child { width: 64px; }

/* The form's record counter (‹ 8/25 ›): the strip's right end (K-232). */
.rax-skel-nav   { flex: none; width: 96px; height: var(--row-h); }

.rax-skel-cell  { width: var(--w, 60%); height: 9px; margin-inline-start: var(--cell-px); }
.rax-skel-head .rax-skel-cell { height: 8px; }

/* The label and the value sit ON THE LINE of the text (`vertical-align`),
   so the text sets the line's height, not the block — the field's height
   stays the same as the real field. */
.rax-skel-label { width: var(--w, 60px); height: 8px; }
.rax-skel-value { width: var(--w, 40%); height: 9px; }

@keyframes rax-skel-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes rax-skel-sweep {
    from { background-position: 100% 0; }
    to   { background-position: 0 0; }
}

@media (prefers-reduced-motion: reduce) {
    .rax-skel-block {
        animation: none;
        background: var(--c-field-line-soft);
    }
}

/* ============================================================
   THE NOTICE OPENING (K-240)

   The dialog appeared in one frame. Now the scrim comes in fading and the
   dialog slightly growing — the eye lands on the middle of the dialog,
   not the scrim. Radzen's dialog grows from 50%; ours from 97%: a notice
   is not a screen but a sentence, an exaggerated growth would make it look
   more important than it is. Closing is instant — so the user who has read
   the result is not kept waiting.
   ============================================================ */
@keyframes rax-scrim-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes rax-dialog-in {
    from { opacity: 0; transform: scale(0.97); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .rax-notice-scrim,
    .rax-notice {
        animation: none;
    }
}

/* ============================================================
   THE SKELETON'S CARD (K-242)

   In a narrow list the row turns into a card (shell.css); had the skeleton
   kept drawing a table, on a phone everything would shift when data
   arrived — K-238's rule «the skeleton must OVERLAP the real screen» would
   break on a narrow screen.

   The card's height comes FROM THE TEXT, not a token: every line is
   `--fs-table × 1.35 + 2 px` (line height + the cell's 1 px padding). The
   skeleton cell is the line box of that height; the bar is in the content
   box (`background-clip`), 9 px.

   The code line is `--fs-table` too: «the code is small» had been written
   as `--fs-caption` and was NEVER applied — the data layer inside the cell
   carries its own size. The skeleton had been drawn for that intent and
   in the wide tier diverged by 3 px on the code line (measured). The
   ineffective rule was deleted.

   COST: the card's number of lines depends on the ENTITY (Warehouses five,
   Customers six); the skeleton is drawn before the definition and assumes
   six.
   ============================================================ */
@container rax-list (max-width: 520px) {
    .rax-skel-head {
        display: none;
    }

    .rax-skel-row {
        grid-template-columns: var(--row-h) minmax(0, 1fr);
        align-items: start;
        height: auto;
        padding-block: var(--sp-2);
        padding-inline-end: var(--pad);
        border-bottom: 1px solid var(--c-field-line);
    }

    /* Selection box: in the real card in the middle of the `--row-h` square. */
    .rax-skel-row::before {
        grid-column: 1;
        grid-row: 1 / span 3;
        margin-block-start: calc((var(--row-h) - 14px) / 2);
    }

    .rax-skel-cell {
        grid-column: 2;
        margin-inline-start: 0;
        /* border-box applies in the tab panel: it takes the 9 px padding
           inside too and the line came out 9 instead of 18 (measured). */
        box-sizing: content-box;
        height: 9px;
        padding-block: calc((var(--fs-table) * 1.35 + 2px - 9px) / 2);
        background-clip: content-box;
    }

    .rax-skel-row > .rax-skel-cell:first-of-type {
        width: 30%;
    }
}

/* ============================================================
   THE SETTINGS PAGE (K-324)

   A sheet, not a grid: the group's title (the form's section title —
   the selector rides on that rule above, not a copy), then one row per
   setting: the label and its key on the left, the value box on the
   right. The bar stays on top while the rows scroll, like the form's
   strip — «Kaydet» does not move.

   ONE COLUMN UNDER 640PX: the label above its box. A two-column row on
   a phone left the box 120px wide; a drop-down of designs did not fit.
   ============================================================ */

/*  THE PAGE CARRIES ITS OWN SCROLL, like the start tab (`.rax-start`): the
    tab panels are `overflow: hidden`, and without this the rows below the
    panel's height could not be reached (measured: 2885 px of rows in a
    518 px panel). The bar is sticky against THIS box. */
.rax-config {
    height: 100%;
    overflow: auto;
}

.rax-config-sheet {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
    padding: 0 var(--pad) var(--pad);
    max-inline-size: 960px;
}

.rax-config-bar {
    position: sticky;
    inset-block-start: 0;
    z-index: 1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2);
    padding-block: var(--sp-3);
    background: var(--c-canvas);
    border-block-end: 1px solid var(--c-field-line);
}

.rax-config-heading {
    font-size: var(--fs-body);
    font-weight: var(--fw-medium);
    color: var(--c-ink);
}

.rax-config-search {
    inline-size: 220px;
    max-inline-size: 100%;
}

.rax-config-spacer {
    flex: 1 1 auto;
}

.rax-config-group {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

.rax-config-row {
    display: grid;
    grid-template-columns: minmax(180px, 2fr) 3fr;
    align-items: center;
    gap: var(--sp-4);
    padding: var(--sp-2) var(--sp-3);
    border-radius: var(--r-control);
}

/* A CHANGED ROW IS MARKED until it is saved: an accent edge and tint —
   the page is long and «what did I change»
   must be answerable by looking. */
.rax-config-row[data-dirty] {
    box-shadow: inset 2px 0 0 var(--c-accent);
    background: color-mix(in srgb, var(--c-accent) 5%, transparent);
}

.rax-config-label {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-inline-size: 0;
    color: var(--c-ink);
    font-size: var(--fs-body);
}

.rax-config-key {
    color: var(--c-ink-3);
    font-size: var(--fs-caption);
    font-family: var(--font-code);
    overflow-wrap: anywhere;
}

.rax-config-value {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    min-inline-size: 0;
}

.rax-config-error {
    color: var(--c-neg);
    font-size: var(--fs-caption);
}

.rax-config-empty {
    padding: var(--sp-5) 0;
    color: var(--c-ink-3);
    font-size: var(--fs-body);
}

@media (max-width: 640px) {
    .rax-config-row {
        grid-template-columns: 1fr;
        gap: var(--sp-2);
    }

    .rax-config-search {
        inline-size: 100%;
        order: 1;
    }
}

/* The drawer's backup line when the daily backup is late or failed (K-329):
   the negative colour, like a refused value — it asks for an action. */
.rax-settings-link small.rax-backup-late {
    color: var(--c-neg);
    font-weight: 600;
}
