﻿/* 10-main.css — ibook24 infrastructure skin.
   extracted from psycho's 10-main.css (infra sections only: tokens, base, buttons/badges/chips,
   blazor system ui, app global elements). public-site sections (nav/hero/shop/articles) were NOT copied. */

/* tokens */
:root {
    /* section backgrounds alias the palette (28/07/2026) — one place to change a brand color */
    --bg-hero: var(--teal);
    --bg-mint: var(--mint);
    --bg-quiz: var(--blue-light);
    --bg-purple: var(--purple);
    --bg-footer: #14252a;
    --footer-text: #8fa8ad;
    --footer-link: #b9cfd4;
    --footer-soft: #6e878c;
    --footer-line: rgba(255, 255, 255, 0.12);
    --mint: #a4e9d6;
    --mint-dark: var(--teal);   /* aligned 28/07/2026 — was #80c6d0, one invisible bit off the brand teal; CTA role stays its own token */
    --mint-soft: #d6f6e8;
    --yellow: #fae45d;
    --blue: #96d7e8;
    --blue-light: #a6deed;
    --purple: #b9bafb;
    --teal: #80c6cf;
    --link: #0f7a8a;         /* readable brand teal for text links */
    --link-hover: #0a5966;
    --ink: #151515;
    --ink-soft: #383636;
    --muted: #686868;
    --line: #e2e4e9;
    --box-border: #ddd;
    --line-strong: #ccc;
    --line-strongX1: #bbb;   /* the house contour step between strong and X3 (named 28/07/2026) */
    --line-strongX2: #aaa;   /* activated 31/08/2026 — the mgr head/foot dashed rules */
    --line-strongX3: #999;
    --danger: #d64545;
    --bg: #ffffff;
    --bg-soft: #f6f7fb;
    --chip-bg: #f1f2f6;
    --chip-bg-hover: #e6e8ef;
    --dot-inactive: #d0d4dc;
    --font: 'Assistant', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --font-display: 'buDrakonit', 'Assistant', system-ui, sans-serif;
    --btn-whoosh: 0.4s ease;  /* one shared hover pace for every button in the system */
    --radius: 18px;
    --radius-lg: 28px;
    --radius-xlg: 70px;
    --shadow-small: 0 3px 10px rgba(0, 0, 0, 0.04);
    --shadow: 0 6px 24px rgba(0, 0, 0, 0.06);
    --shadow-lg: 0 20px 60px rgba(0, 0, 0, 0.10);
    /* the ONE dimming layer behind menus/drawers (tokenized 08/08/2026; unified on the mgr's
       deep-blue value — the public backdrop was rgba(0,0,0,.35), one invisible step lighter) */
    --overlay: rgba(15, 23, 42, 0.45);
    --container: 1240px;
    --section-px: 16px;
    --bleed-inset: max(var(--section-px), calc(50% - var(--container) / 2));
    /* heading scale — content headings, applied inside .page-body */
    --heading-1: 2.5rem;
    --heading-2: 1.875rem;
    --heading-3: 1.5rem;
    --heading-4: 1.25rem;
    /* content text — one size, one rhythm (decided 08/08/2026); the only other approved size is --text-sm */
    --text-body: 1.125rem;   /* = 18px */
    --text-sm: 0.9375rem;    /* = 15px — meta, captions, legal lines */
    --text-lh: 1.5;
    --heading-5: 1.125rem;
    --heading-6: 1rem;
    /* shared-ui tokens — the element layer both worlds drink from (promoted from 20-mgr, 25/07/2026).
       20-mgr keeps --mgr-* aliases pointing here, so mgr code keeps reading its own names. */
    --row-hover: #fdf6dd;      /* warm brand-yellow tint — since 29/07/2026 the CURRENT-row fill (hover went blue-soft); also filter-menu highlight + flicker */
    --row-stripe: #fbfbfb;     /* whisper-light zebra stripe — shared by the tablegrid and the .table skin (tokenized 30/07/2026) */
    --ui-bg-soft: #f4f7fb;
    --ui-hover: #dce4ee;
    --ui-frame: #e8edf4;
    --ui-border: #d5dde8;
    --ui-border-strong: #c3cfdd;
    --ui-deep: #16233a;
    --ui-heading: #2b3a52;
    --ui-text-soft: #74839e;
    --ui-text-faint: #9daabf;
    --ui-blue: #0060b4;
    --ui-blue-soft: #e9f4ff;
    --ui-danger: #dc2626;
    --ui-danger-bg: #fdf0f0;
    /* --ui-field-bg retired 30/07/2026 — fields are white at rest in both engines */
    /* field skin — ONE source for every input kind (unified 31/07/2026): white at rest, soft gray
       hint on hover; focus = readable-teal border + soft teal glow (teal focus decided 08/08/2026,
       same accent as the public form__ fields). consumed by .app-form, .imgpick__trigger and
       the radzen fields (datepicker / autocomplete / grid filter / html editor) in 30-radzen-fix. */
    --field-bg: #fff;
    --field-bg-hover: var(--ui-bg-soft);
    --field-border: var(--ui-border);
    --field-border-focus: var(--link);
    /* focus ring (ibook 23/08/2026): a crisp 1px hairline, not a 3px halo — thin and clear */
    --field-glow: 0 0 0 1px var(--teal);
    --field-border-invalid: var(--ui-danger);
    /* THE two focus languages (11/08/2026): these tokens are the ONLY focus definitions in the
       system — public values here, the mgr override lives in .mgr-root (20-mgr). one bare global
       rule (form section) applies them to every field; family skins define NO focus of their own. */
    --focus-border: var(--teal);
    --focus-glow: 0 0 0 1px var(--teal);
    --focus-border-danger: var(--danger);
    --focus-glow-danger: 0 0 0 1px var(--danger);
    --field-radius: 0.375rem;
    --field-font-size: 0.875rem;
    --field-padding-y: 0.25rem;
    --field-padding-x: 0.5rem;
    --field-select-padding-end: 2.25rem;
    --ui-radius-sm: 0.5rem;
    --ui-radius-md: 0.75rem;
    --ui-shadow-sm: 0 3px 12px rgba(43, 58, 82, 0.07);
    --ui-shadow-md: 0 12px 32px rgba(37, 68, 120, 0.13);
    --ui-ease: cubic-bezier(0.22, 1, 0.36, 1);
    --ui-fast: 0.18s var(--ui-ease);
    --ui-medium: 0.3s var(--ui-ease);
    --ui-control-h: 2.375rem;
    /* state palette — the ONE source for both engines (decided 28/07/2026):
       the bootstrap .btn skin below and radzen's --rz-* (30-radzen-fix) both map here.
       hover = bootstrap hover / radzen dark; active = bootstrap active / radzen darker. */
    --state-primary: #4e737a; --state-primary-hover: #435e64; --state-primary-active: #3c545a;
    --state-secondary: #74839e; --state-secondary-hover: #66748d; --state-secondary-active: #5d6a82;
    --state-success: #2e8f6e; --state-success-hover: #287d60; --state-success-active: #247257;
    --state-danger: #d64545; --state-danger-hover: #c23d3d; --state-danger-active: #b13838;
    --state-warning: #edc953; --state-warning-hover: #e3bc3f; --state-warning-active: #d9b338;
    --state-info: #0d6efd; --state-info-hover: #0b5ed7; --state-info-active: #0a58ca;
    /* the four roles that used to carry their own literals — tokenised 30/07/2026.
       same values as before, one home each; base/light also own their text + contour. */
    --state-submit: #1976d2; --state-submit-hover: #1565c0; --state-submit-active: #0d47a1;
    --state-base: #dadfe2; --state-base-hover: #cdd4d8; --state-base-active: #c1c9cb;
    --state-base-text: #28363c; --state-base-border-hover: #aaa;
    --state-light: #ffffff; --state-light-hover: #f4f7fb; --state-light-active: #e9edf0;
    --state-light-text: #2b3a52; --state-light-border-hover: #aaa;
    --state-dark: #343a40; --state-dark-hover: #2b3035; --state-dark-active: #23272b;
    /* soft palette — the ONE source for badges, chips and alerts (30/07/2026);
       the three families used to repeat these fills and contours between them. */
    --soft-success-bg: #e5f5ec; --soft-success-text: #1c7c4c; --soft-success-border: #86c3a4;
    --soft-warning-bg: #fcf4d7; --soft-warning-text: #8a6d1d; --soft-warning-border: #e0c46a;
    --soft-danger-bg: #fdecec; --soft-danger-text: #b13838; --soft-danger-border: #e39aa2;
    --soft-info-bg: #e7f0fe; --soft-info-text: #0a58ca; --soft-info-border: #9ec5fe;
    --soft-base-bg: #e8edf4; --soft-base-text: #4a5a74; --soft-base-border: var(--ui-border-strong);
}

@media (min-width: 992px) {
    :root {
        --heading-1: 3.125rem;
        --heading-2: 2.375rem;
        --heading-3: 1.875rem;
        --heading-4: 1.375rem;
    }
}

@media (min-width: 1200px) {
    :root { --section-px: 32px; }
}

/* headings — site-wide base (font only); overrides Bootstrap defaults */
h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-display);
    font-weight: 700;
    line-height: 1.1;
    margin: 0 0 .5em;
}
/* h2 variants: centered title with a dividing line on both sides — one body (merged 28/07/2026);
   h2_v2 = h2_v1 wearing the ui-blue ink (chosen 25/07/2026; the elements catalog headings);
   h2_v3 = the quiet small h2 — text font instead of the display font, which is unreadable
   this small (decided 08/08/2026); h2_v4 = h2_v3 centered with the dividing lines */
.h2_v1,
.h2_v2,
.h2_v4 {
    display: flex;
    align-items: center;
    gap: 1rem;
    text-align: center;
}
.h2_v2 { color: var(--ui-blue); }
.h2_v3,
.h2_v4 {
    font-family: var(--font);
    font-weight: 700;
    font-size: 1.2rem;
}
.h2_v1::before,
.h2_v1::after,
.h2_v2::before,
.h2_v2::after,
.h2_v4::before,
.h2_v4::after {
    content: "";
    flex: 1;
    border-top: 1px solid var(--line);
}

/* hr variants: house dividers (base <hr> stays bootstrap's default) */
hr.hr_v1 { border-top-style: dashed; }
hr.hr_v2 { border-top-width: 3px; opacity: 0.4; }
hr.hr_v3 {
    width: 6rem;
    margin-inline: auto;
    border-top-width: 3px;
    border-radius: 999px;
    opacity: 0.6;
}
hr.hr_v4 {
    width: 6rem;
    margin-inline: auto;
}
hr.hr_v5 {
    border-top-style: dashed;
    margin-block: 2.5rem;
}

/* accordion — native details/summary in the house look:
   sidebar-style chevron that turns down on open, whoosh reveal for the content */
details > summary {
    list-style: none;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    cursor: pointer;
}
details > summary::-webkit-details-marker { display: none; }
details > summary::before {
    content: "\f053";   /* fa chevron, pointing "closed" */
    font-family: "Font Awesome 6 Free";
    font-weight: 900;
    font-size: 0.75rem;
    transition: transform var(--btn-whoosh);
}
details[open] > summary::before { transform: rotate(-90deg); }
details[open] > summary ~ * { animation: psyc-acc-in var(--btn-whoosh); }
@keyframes psyc-acc-in {
    from { opacity: 0; transform: translateY(-0.25rem); }
    to { opacity: 1; transform: none; }
}

/* link variants: house links — lnk & lnk1 share one body; lnk1 is the EMPHASIZED link in
   public (700, decided 08/08/2026) and the quiet ink link in the mgr (20-mgr recolors it
   and pins its weight back). the two names stay. */
a.lnk,
a.lnk1 {
    color: var(--link);
    font-weight: 600;
    text-decoration: none;
}
a.lnk1 { font-weight: 700; }
a.lnk:hover,
a.lnk1:hover { text-decoration: underline; text-underline-offset: 0.15em; }
/* links inside tables style themselves — a bare <a> gets the table-link look,
   so there is no class to remember (.btn/.lnk keep their own skins) */
.tablegrid a:not(.btn):not(.lnk),
.mgr-page-body .table a:not(.btn):not(.lnk) {
    color: var(--link);
    font-weight: 600;
    text-decoration: none;
}
.tablegrid a:not(.btn):not(.lnk):hover,
.mgr-page-body .table a:not(.btn):not(.lnk):hover { text-decoration: underline; text-underline-offset: 0.15em; }
/* content heading sizes — public envelope + page body; :where() keeps component classes winning */
:where(.page-body, .main-page) h1 { font-size: var(--heading-1); }
:where(.page-body, .main-page) h2 { font-size: var(--heading-2); }
:where(.page-body, .main-page) h3 { font-size: var(--heading-3); }
:where(.page-body, .main-page) h4 { font-size: var(--heading-4); }
:where(.page-body, .main-page) h5 { font-size: var(--heading-5); }
:where(.page-body, .main-page) h6 { font-size: var(--heading-6); }

/* base */
body {
    font-family: var(--font);
    /* the one base — content text size and rhythm come from the tokens (decided 08/08/2026) */
    font-size: var(--text-body);
    line-height: var(--text-lh);
    color: var(--ink);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;
}
p { margin: 0 0 1em; }
a { color: inherit; text-decoration: none; }
img, video { max-width: 100%; height: auto; display: block; }
button { font: inherit; cursor: pointer; }

/* inline code — an LTR island inside hebrew prose (30/07/2026).
   without `isolate` the bidi algorithm drags neutral leading characters to the other end:
   `--state-*` rendered as `*-state--`, `?tab=` as `tab=?`, `10-main` as `main-10`.
   every token name in the catalog was displayed wrong until this rule existed. */
code {
    direction: ltr;
    unicode-bidi: isolate;
}
/* the chip look marks where the LTR island starts and ends — worth more in RTL than in LTR.
   `:not(pre)` keeps the catalog's code BLOCK (.gal-code) flat. */
:not(pre) > code {
    padding: 0.05em 0.35em;
    border-radius: 0.25rem;
    background: var(--ui-bg-soft);
    color: var(--ui-deep);
}

/* box — single source of truth for the gray surface card. Padding/layout stay per component. */
.box {
    background: var(--bg-soft);
    border: 1px solid var(--box-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-small);
}

/* skip-link — hidden until keyboard focus, then floats above the nav.
   one base for both worlds (merged 28/07/2026); 20-mgr keeps only the mgr look overrides. */
.skip-link,
.mgr-skip-link {
    position: fixed;
    inset-block-start: 0.5rem;
    inset-inline-start: 0.5rem;
    z-index: 1100;
    padding: 0.5rem 0.75rem;
    background: #fff;
    transform: translateY(-150%);
}
.skip-link {
    border-radius: var(--radius);
    color: var(--ink);
    font-weight: 600;
    box-shadow: var(--shadow);
}
.skip-link:focus,
.mgr-skip-link:focus {
    transform: none;
}


/* ============================================================
   our buttons = bootstrap .btn + this house skin (locked 19/07/2026)
   shape, whoosh pace, and the approved palette mapped onto .btn-*
   ============================================================ */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    height: 2.375rem;
    padding: 0 1rem;
    font-family: var(--font);
    font-size: 1rem;
    font-weight: 600;
    border-radius: 0.5rem;
    --bs-btn-disabled-opacity: 0.5;
    transition: background-color var(--btn-whoosh), border-color var(--btn-whoosh), color var(--btn-whoosh);
}
/* btn-link — bootstrap's link-shaped button, for a click action that sits inside text or a
   table cell (replaced the empty-href anchor pattern, 02/09/2026): no box, flows like a link
   and wears the house table-link look (same as the bare <a> rule above).
   .btn.btn-link so it also beats the mobile .btn height override below */
.btn.btn-link {
    display: inline;
    height: auto;
    padding: 0;
    font-size: inherit;
    font-weight: 600;
    vertical-align: baseline;
    --bs-btn-color: var(--link);
    --bs-btn-hover-color: var(--link);
    --bs-btn-active-color: var(--link);
    text-decoration: none;
}
.btn.btn-link:hover { text-decoration: underline; text-underline-offset: 0.15em; }
.btn-lg { height: 2.875rem; padding: 0 1.375rem; font-size: 1.125rem; border-radius: 0.5rem; }
.btn-sm { height: 1.875rem; padding: 0 0.75rem; font-size: 0.875rem; border-radius: 0.5rem; }
/* btn-xs / btn-xxs — house size extensions (bootstrap dropped xs in v4): for dense toolbars */
.btn-xs { height: 1.5rem; padding: 0 0.5rem; font-size: 0.8rem; border-radius: 0.375rem; }
.btn-xxs { height: 1.25rem; padding: 0 0.375rem; font-size: 0.75rem; border-radius: 0.375rem; }

/* filled — the approved palette (smoked teal primary, calm blue info, deep brand teal dark) */
.btn-primary {
    --bs-btn-bg: var(--state-primary); --bs-btn-border-color: var(--state-primary);
    --bs-btn-hover-bg: var(--state-primary-hover); --bs-btn-hover-border-color: var(--state-primary-hover);
    --bs-btn-active-bg: var(--state-primary-active); --bs-btn-active-border-color: var(--state-primary-active);
    --bs-btn-disabled-color: #fff;
    --bs-btn-disabled-bg: var(--state-primary); --bs-btn-disabled-border-color: var(--state-primary);
    --bs-btn-focus-shadow-rgb: 78, 115, 122;
}
.btn-secondary {
    --bs-btn-bg: var(--state-secondary); --bs-btn-border-color: var(--state-secondary);
    --bs-btn-hover-bg: var(--state-secondary-hover); --bs-btn-hover-border-color: var(--state-secondary-hover);
    --bs-btn-active-bg: var(--state-secondary-active); --bs-btn-active-border-color: var(--state-secondary-active);
    --bs-btn-disabled-color: #fff;
    --bs-btn-disabled-bg: var(--state-secondary); --bs-btn-disabled-border-color: var(--state-secondary);
    --bs-btn-focus-shadow-rgb: 116, 131, 158;
}
.btn-success {
    --bs-btn-bg: var(--state-success); --bs-btn-border-color: var(--state-success);
    --bs-btn-hover-bg: var(--state-success-hover); --bs-btn-hover-border-color: var(--state-success-hover);
    --bs-btn-active-bg: var(--state-success-active); --bs-btn-active-border-color: var(--state-success-active);
    --bs-btn-disabled-color: #fff;
    --bs-btn-disabled-bg: var(--state-success); --bs-btn-disabled-border-color: var(--state-success);
    --bs-btn-focus-shadow-rgb: 46, 143, 110;
}
.btn-danger {
    --bs-btn-bg: var(--state-danger); --bs-btn-border-color: var(--state-danger);
    --bs-btn-hover-bg: var(--state-danger-hover); --bs-btn-hover-border-color: var(--state-danger-hover);
    --bs-btn-active-bg: var(--state-danger-active); --bs-btn-active-border-color: var(--state-danger-active);
    --bs-btn-disabled-color: #fff;
    --bs-btn-disabled-bg: var(--state-danger); --bs-btn-disabled-border-color: var(--state-danger);
    --bs-btn-focus-shadow-rgb: 214, 69, 69;
}
.btn-warning {
    --bs-btn-color: var(--ink);
    --bs-btn-bg: var(--state-warning); --bs-btn-border-color: var(--state-warning);
    --bs-btn-hover-color: var(--ink);
    --bs-btn-hover-bg: var(--state-warning-hover); --bs-btn-hover-border-color: var(--state-warning-hover);
    --bs-btn-active-color: var(--ink);
    --bs-btn-active-bg: var(--state-warning-active); --bs-btn-active-border-color: var(--state-warning-active);
    --bs-btn-disabled-color: var(--ink);
    --bs-btn-disabled-bg: var(--state-warning); --bs-btn-disabled-border-color: var(--state-warning);
    --bs-btn-focus-shadow-rgb: 237, 201, 83;
}
.btn-info {
    --bs-btn-color: #fff;
    --bs-btn-bg: var(--state-info); --bs-btn-border-color: var(--state-info);
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: var(--state-info-hover); --bs-btn-hover-border-color: var(--state-info-hover);
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: var(--state-info-active); --bs-btn-active-border-color: var(--state-info-active);
    --bs-btn-disabled-color: #fff;
    --bs-btn-disabled-bg: var(--state-info); --bs-btn-disabled-border-color: var(--state-info);
    --bs-btn-focus-shadow-rgb: 13, 110, 253;
}
/* btn-submit — house extension (like .btn-base): the ONE default action of a form.
   material blue (#1976d2), deliberately distinct from btn-primary (dialogs' calm teal)
   and from btn-info. one per form; the rest keep their regular families. */
.btn-submit {
    --bs-btn-color: #fff;
    --bs-btn-bg: var(--state-submit); --bs-btn-border-color: var(--state-submit);
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: var(--state-submit-hover); --bs-btn-hover-border-color: var(--state-submit-hover);
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: var(--state-submit-active); --bs-btn-active-border-color: var(--state-submit-active);
    --bs-btn-disabled-color: #fff;
    --bs-btn-disabled-bg: var(--state-submit); --bs-btn-disabled-border-color: var(--state-submit);
    --bs-btn-focus-shadow-rgb: 25, 118, 210;
}
/* badges — bootstrap .badge in the house soft-fill look: tinted background, dark text, pill */
.badge {
    font-family: var(--font);
    font-size: 0.8125rem;
    font-weight: 600;
    padding: 0.125rem 0.625rem;
    border-radius: 999px;
}
/* the soft badges carry a contour from 30/07/2026 — same tokens the chips already wear.
   without it the fill sits at ~1.01 contrast against any tinted surface (a coloured card
   header, a highlighted row) and the badge simply dissolves. */
.badge-soft-success { background: var(--soft-success-bg); color: var(--soft-success-text); border: 1px solid var(--soft-success-border); }
.badge-soft-base { background: var(--soft-base-bg); color: var(--soft-base-text); border: 1px solid var(--soft-base-border); }
.badge-soft-warning { background: var(--soft-warning-bg); color: var(--soft-warning-text); border: 1px solid var(--soft-warning-border); }
.badge-soft-danger { background: var(--soft-danger-bg); color: var(--soft-danger-text); border: 1px solid var(--soft-danger-border); }
.badge-soft-info { background: var(--soft-info-bg); color: var(--soft-info-text); border: 1px solid var(--soft-info-border); }
/* the ONE loud badge (11/08/2026) — filled info blue, reserved for "action required" states
   (e.g. order status "למשלוח"): in a list of quiet softs, exactly one thing may shout */
.badge-loud-info { background: var(--state-info); color: #fff; border: 1px solid var(--state-info); }

/* chips — interactive pills: "a badge with a handle". the border, white fill and hand
   cursor on the ✕ are what visually separate them from the passive badge family */
.chip {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0 0.625rem;
    border: 1px solid var(--line-strong);
    border-radius: 999px;
    background: #fff;
    font-family: var(--font);
    /* the text reads like a regular paragraph — body size and weight, house ink */
    font-size: 0.8rem;
    font-weight: 400;
    /* pinned so the chip is the same height in every context (grid header, page body...);
       1.3 keeps the pill at its original height after the body-size text bump */
    line-height: 1.3;
    color: var(--ink, #151515);
}
.chip__x {
    border: 0;
    padding: 0;
    background: none;
    cursor: pointer;
    color: var(--muted, #686868);
    font-size: 0.8125rem;
    line-height: 1;
    transition: color var(--btn-whoosh);
}
.chip__x:hover { color: var(--danger, #d64545); }
button.chip, .chip[role="button"] { cursor: pointer; }
/* chip color variants — the badge-soft palette wearing the chip's interactive contour.
   text stays the house ink on all of them (only the fill and contour change) */
.chip-success { background: var(--soft-success-bg); border-color: var(--soft-success-border); }
.chip-warning { background: var(--soft-warning-bg); border-color: var(--soft-warning-border); }
.chip-danger { background: var(--soft-danger-bg); border-color: var(--soft-danger-border); }
.chip-info { background: var(--soft-info-bg); border-color: var(--soft-info-border); }

/* alert1 — house modifier for bootstrap alerts (`alert alert-* alert1`):
   keeps the variant's frame, adds a start-side accent bar */
.alert.alert1 {
    border-inline-start: 3px solid #2f9ec4;
    border-radius: 0.5rem;
    padding: 0.75rem 1rem;
}
/* alert color tuning — text on the house ink, frames a shade stronger than bootstrap's */
.alert { color: var(--ink); }
.alert-success { border-color: var(--soft-success-border); }
.alert-warning { border-color: var(--line-strong); }
.alert-danger { border-color: var(--soft-danger-border); }

/* card-head-info — bootstrap .card wearing a tinted header (30/07/2026): the soft blue
   highlight surface, for a dashboard card that should lead the eye. the body stays on the
   page paper, so only the header carries the colour. */
.card-head-info > .card-header {
    background: var(--ui-blue-soft);
    border-bottom-color: var(--ui-border);
    color: var(--ui-heading);
    font-weight: 600;
}

/* checks, radios & switches — checked state in the house teal instead of bootstrap blue,
   and comfortable sizes (bootstrap's 1em box is too small next to our fields) */
.form-check {
    padding-inline-start: 1.75rem;
    min-height: 1.5rem;
}
.form-check .form-check-input {
    width: 1.25rem;
    height: 1.25rem;
    margin-inline-start: -1.75rem;
    margin-top: 0.125rem;
}
.form-switch {
    padding-inline-start: 3rem;
}
.form-switch .form-check-input {
    width: 2.5rem;
    margin-inline-start: -3rem;
}
.form-check-input:checked {
    background-color: var(--state-primary);
    border-color: var(--state-primary);
}
.form-check-input:focus {
    border-color: var(--state-primary);
    box-shadow: 0 0 0 0.25rem rgba(78, 115, 122, 0.25);
}

/* base — the soft gray (borrowed from radzen software, the dialogs' cancel); a house extension, not a bootstrap default */
.btn-base {
    --bs-btn-color: var(--state-base-text);
    --bs-btn-bg: var(--state-base); --bs-btn-border-color: var(--line-strongX1);
    --bs-btn-hover-color: var(--state-base-text);
    --bs-btn-hover-bg: var(--state-base-hover); --bs-btn-hover-border-color: var(--state-base-border-hover);
    --bs-btn-active-color: var(--state-base-text);
    --bs-btn-active-bg: var(--state-base-active); --bs-btn-active-border-color: var(--state-base-border-hover);
    --bs-btn-disabled-color: var(--state-base-text);
    --bs-btn-disabled-bg: var(--state-base); --bs-btn-disabled-border-color: var(--line-strongX1);
    --bs-btn-focus-shadow-rgb: 218, 223, 226;
}
/* light = "the quiet white one" — the classic house button (white, #ccc contour, dark text) */
.btn-light {
    --bs-btn-color: var(--state-light-text);
    --bs-btn-bg: var(--state-light); --bs-btn-border-color: var(--line-strong);
    --bs-btn-hover-color: var(--state-light-text);
    --bs-btn-hover-bg: var(--state-light-hover); --bs-btn-hover-border-color: var(--state-light-border-hover);
    --bs-btn-active-color: var(--state-light-text);
    --bs-btn-active-bg: var(--state-light-active); --bs-btn-active-border-color: var(--state-light-border-hover);
    --bs-btn-disabled-color: var(--state-light-text);
    --bs-btn-disabled-bg: var(--state-light); --bs-btn-disabled-border-color: var(--line-strong);
    --bs-btn-focus-shadow-rgb: 204, 204, 204;
}
.btn-dark {
    --bs-btn-bg: var(--state-dark); --bs-btn-border-color: var(--state-dark);
    --bs-btn-hover-bg: var(--state-dark-hover); --bs-btn-hover-border-color: var(--state-dark-hover);
    --bs-btn-active-bg: var(--state-dark-active); --bs-btn-active-border-color: var(--state-dark-active);
    --bs-btn-disabled-color: #fff;
    --bs-btn-disabled-bg: var(--state-dark); --bs-btn-disabled-border-color: var(--state-dark);
    --bs-btn-focus-shadow-rgb: 52, 58, 64;
}

/* gf.Vi() / gf.Ex() — big center-screen flash, auto-fades (GfOverlay) */
.gf-flash {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    z-index: 2000;
}
.gf-flash i {
    font-size: 6rem;
    animation: gf-flash-pop 0.8s ease forwards;
}
.gf-flash--ok { color: var(--state-success); }
.gf-flash--fail { color: var(--state-danger); }
@keyframes gf-flash-pop {
    0% { opacity: 0; transform: scale(0.5); }
    20% { opacity: 1; transform: scale(1.1); }
    35% { transform: scale(1); }
    75% { opacity: 1; }
    100% { opacity: 0; }
}

/* gf.Busy() — blocking screen spinner / quiet corner spinner (GfElements) */
.gf-busy--block {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.55);
    z-index: 2100;
}
.gf-busy--block i { font-size: 3.5rem; color: var(--state-primary); }
.gf-busy--quiet {
    position: fixed;
    inset-inline-end: 1.25rem;
    inset-block-end: 1.25rem;
    pointer-events: none;
    z-index: 2100;
}
.gf-busy--quiet i { font-size: 1.75rem; color: var(--state-primary); }

/* small inline feedback (success after submit) */
.form-note {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 18px 0 0;
    padding: 14px 18px;
    border-radius: var(--radius);
    background: var(--mint-soft);
    color: var(--ink);
    font-weight: 700;
}
.form-note i { color: var(--mint-dark); font-size: 1.2rem; }

/* ---------------------------------------------------------------- 11. Blazor system UI ---- */
#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    inset-inline-end: 0;
    padding: 0.6rem 1.25rem 0.7rem;
    position: fixed;
    width: 100%;
    /* above the mgr shell (sidebar 1045 / topbar 1050) — the error strip must never be covered */
    z-index: 1060;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    inset-inline-start: 0.75rem;
    top: 0.5rem;
    /* the dismiss is a real <button> — strip the browser chrome so it stays the bare glyph */
    border: 0;
    background: none;
    padding: 0;
    font: inherit;
}

.components-reconnect-first-attempt-visible,
.components-reconnect-repeated-attempt-visible,
.components-reconnect-failed-visible,
.components-pause-visible,
.components-resume-failed-visible,
.components-rejoining-animation {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible,
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation,
#components-reconnect-modal.components-reconnect-paused .components-pause-visible,
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible,
#components-reconnect-modal.components-reconnect-retrying,
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible,
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible {
    display: block;
}

#components-reconnect-modal {
    background-color: white;
    width: 20rem;
    margin: 20vh auto;
    padding: 2rem;
    border: 0;
    border-radius: 0.5rem;
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3);
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity 0.5s both;
}

#components-reconnect-modal[open] {
    animation: components-reconnect-modal-slideUp 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

#components-reconnect-modal::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button {
    border: 0;
    background-color: #6b9ed2;
    color: white;
    padding: 4px 24px;
    border-radius: 4px;
}

#components-reconnect-modal button:hover {
    background-color: #3b6ea2;
}

#components-reconnect-modal button:active {
    background-color: #6b9ed2;
}

.components-rejoining-animation {
    position: relative;
    width: 80px;
    height: 80px;
}

.components-rejoining-animation div {
    position: absolute;
    border: 3px solid #0087ff;
    opacity: 1;
    border-radius: 50%;
    animation: components-rejoining-animation 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
}

.components-rejoining-animation div:nth-child(2) {
    animation-delay: -0.5s;
}

@keyframes components-rejoining-animation {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0;
        left: 0;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}


/* ============================================================
   shared ui elements — promoted from 20-mgr (25/07/2026).
   renamed 27/07/2026 (ex mgr-*): app-form family, imgpick;
   these work on every page, public included. tokens: --ui-* / --row-hover.
   ============================================================ */

/* top-ctr-bar deleted 30/07/2026 — the top action bar retired 29/07 in favour of the merged
   page head (<MgrHeadBtns>); the skin lab, its last consumer, was aligned to the new pattern */

/* --- form family --- */
/* check/radio/switch labels are running text — undo the small bold field-label styling */
.app-form .form-check-label {
    display: inline;
    margin-bottom: 0;
    font-size: 1rem;
    font-weight: 400;
    color: var(--ink);
    white-space: normal;
}
/* .app-label — the same look for a "label" that has no labelable control (e.g. the html editor),
   so it can be a <p> instead of an orphan <label> (10/08/2026) */
.app-form label,
.app-form .app-label {
    display: block;
    margin-bottom: 0.2rem;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--ui-heading);
    white-space: nowrap;
}
/* required marker — red, after the label text (decided 30/07/2026) */
.app-form label > span,
.app-form .app-label > span { color: var(--ui-danger); }
.app-field-foot {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
}
.app-field-foot .invalid-feedback { margin: 0; }
.app-count {
    margin-inline-start: auto;
    font-size: 0.75rem;
    color: var(--ui-text-faint);
}
.app-count--warn { color: var(--ui-danger); font-weight: 600; }
/* mgr fields — one size everywhere (form-select-sm metrics): skin, contour, typography.
   applies to every text box and combo in mgr, filter bars and side panels alike. */
.mgr-root .form-control,
.mgr-root .form-select {
    background-color: var(--field-bg);
    border-color: var(--field-border);
    border-radius: var(--field-radius);
    color: var(--ui-deep);
    font-size: var(--field-font-size);
    line-height: 1.5;
    padding-block: var(--field-padding-y);
    transition: border-color var(--ui-fast), background-color var(--ui-fast);
}
.mgr-root .form-control:not(textarea) {
    padding-inline: var(--field-padding-x);
}
.mgr-root .form-select {
    padding-inline-start: var(--field-padding-x);
    padding-inline-end: var(--field-select-padding-end);
}
.mgr-root textarea.form-control {
    padding: var(--field-padding-y) var(--field-padding-x);
}
.app-form .form-check-input { font-size: 1rem; }
.mgr-root .form-control::placeholder { color: var(--ui-text-faint); }
.mgr-root .form-control:disabled,
.mgr-root .form-select:disabled {
    background-color: var(--ui-frame);
    border-color: var(--ui-border);
    color: var(--ui-text-soft);
    cursor: not-allowed;
}
.mgr-root .form-control:hover:not(:disabled):not(:focus),
.mgr-root .form-select:hover:not(:disabled):not(:focus) {
    background-color: var(--field-bg-hover);
}
/* app-form focus deleted 11/08/2026 — THE global focus rule serves every field */
/* error state — the house red instead of bootstrap's foreign #dc3545 (decided 08/08/2026) */
.app-form .form-control.is-invalid,
.app-form .form-select.is-invalid,
.app-form .form-control.invalid,
.app-form .form-select.invalid {
    border-color: var(--field-border-invalid);
}
.app-form .invalid-feedback,
.app-form .validation-message {
    display: block;
    margin-top: 0.25rem;
    font-size: 0.8125rem;
    color: var(--ui-danger);
}
/* three zones: status on the start side, the main save dead-center, state actions (unpublish/delete) on the end side */
.app-form-actions {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 0.75rem;
    margin-top: 2rem;
}
/* the buttons centered (FormActions, 08/10/2026 from psycho): the main one and the record's extra buttons */
.app-form-actions__btns { display: flex; gap: 0.75rem; justify-content: center; }
.app-form-actions__end { display: flex; gap: 0.75rem; justify-content: flex-end; }
/* the status line: under the buttons, after a rule - the status (dirty note, dates) at the start of the line,
   the quiet links (a delete, a back link) at its end */
.app-form-status-rule { margin: 1.25rem 0 0.75rem; border-top: 1px solid var(--ui-border); opacity: 1; }
.app-form-status { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; color: var(--ui-text-soft); font-size: 0.875rem; }
.app-form-status__links { display: flex; gap: 0.75rem; }
/* narrow screens: the three zones stack (status, save, state actions) instead of squeezing */
@media (max-width: 575.98px) {
    .app-form-actions {
        grid-template-columns: 1fr;
        justify-items: center;
        gap: 0.5rem;
    }
    .app-form-actions__end { justify-content: center; }
}

/* transaction-form box (30/07/2026): a complex form gets a self-frame like the table's —
   a fill slightly deeper than the page paper makes the white fields pop; quiet, no shadow.
   rule: box = transaction form only, never a general page box (that one retired 29/07/2026).
   on narrow screens (fields stacked) the box vanishes and the form sits bare on the page. */
.app-form-box {
    padding: 1.5rem;
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius-md);
    background: color-mix(in srgb, var(--ui-bg-soft) 55%, var(--mgr-bg, #fff));
}
/* the three-zone footer is part of the transaction — it lives inside the box, behind a soft rule */
.app-form-box .app-form-actions {
    padding-top: 1.25rem;
    border-top: 1px solid var(--ui-border);
}
@media (max-width: 767.98px) {
    .app-form-box {
        padding: 0;
        border: 0;
        border-radius: 0;
        background: none;
    }
    .app-form-box .app-form-actions {
        padding-top: 0;
        border-top: 0;
    }
}

/* section fieldset (13/08/2026): a complex form groups its flag/status areas in framed boxes
   whose plain-bold title sits ON the top border — the native fieldset+legend notch, restored
   from bootstrap's reboot (its legend float:left kills the classic look) */
.app-fieldset {
    height: 100%;
    padding: 0.25rem 1rem 0.75rem;
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius-md);
    background: #fff;
}
.app-fieldset > legend {
    float: none;
    width: auto;
    padding: 0 0.5rem;
    margin-bottom: 0;
    font-size: inherit;
    font-weight: 700;
}

/* --- tables — bootstrap .table wearing the house skin (moved from 20-mgr 27/07/2026; applies inside
   the mgr page body, and since 10/08/2026 also inside mgr dialogs — the radzen portal lives in
   .mgr-root but outside .mgr-page-body, and a house table must look the same in both) --- */
.mgr-page-body .table,
.mgr-page-foot .table,
.mgr-root .rz-dialog .table {
    --bs-table-bg: var(--bg);
    /* zebra (when .table-striped is worn): the same whisper-light stripe as the tablegrid */
    --bs-table-striped-bg: var(--row-stripe);
    /* frame + header line on the house hard line — same vocabulary as the tablegrid (unified 26/07/2026) */
    border: 1px solid var(--line-strong);
    /* rounded frame (28/07/2026): separate collapse so the radius can exist; corner cells rounded below */
    border-radius: var(--ui-radius-sm);
    border-collapse: separate;
    border-spacing: 0;
}
.mgr-page-body .table > thead th:first-child,
.mgr-page-foot .table > thead th:first-child,
.mgr-root .rz-dialog .table > thead th:first-child { border-start-start-radius: calc(var(--ui-radius-sm) - 1px); }
.mgr-page-body .table > thead th:last-child,
.mgr-page-foot .table > thead th:last-child,
.mgr-root .rz-dialog .table > thead th:last-child { border-start-end-radius: calc(var(--ui-radius-sm) - 1px); }
.mgr-page-body .table > tbody tr:last-child td:first-child,
.mgr-page-foot .table > tbody tr:last-child td:first-child,
.mgr-root .rz-dialog .table > tbody tr:last-child td:first-child { border-end-start-radius: calc(var(--ui-radius-sm) - 1px); }
.mgr-page-body .table > tbody tr:last-child td:last-child,
.mgr-page-foot .table > tbody tr:last-child td:last-child,
.mgr-root .rz-dialog .table > tbody tr:last-child td:last-child { border-end-end-radius: calc(var(--ui-radius-sm) - 1px); }
.mgr-page-body .table > thead th,
.mgr-page-foot .table > thead th,
.mgr-root .rz-dialog .table > thead th {
    text-align: start;
    padding: 0.625rem 0.75rem;
    background: var(--ui-bg-soft);
    color: var(--ui-heading);
    font-size: 0.875rem;
    /* field names are BOLD — the house method (31/08/2026, was 600) */
    font-weight: 700;
    border-bottom: 1px solid var(--line-strong);
}
.mgr-page-body .table > tbody td,
.mgr-page-foot .table > tbody td,
.mgr-root .rz-dialog .table > tbody td,
.mgr-root .rz-dialog-side .table > tbody td {
    padding: 0.625rem 0.75rem;
    /* = the mgr --text-body (15px); the token resolves inside .mgr-root */
    font-size: var(--text-body);
    /* row separators aligned to the tablegrid's line weight (the grid is the model, 26/07/2026) */
    border-bottom: 1px solid var(--ui-border);
    /* hover eases in softly instead of snapping — same pace as the radzen tablegrid */
    transition: background-color var(--ui-fast);
}
.mgr-page-body .table > tbody tr:last-child td,
.mgr-page-foot .table > tbody tr:last-child td { border-bottom: 0; }
.mgr-root .rz-dialog .table > tbody tr:last-child td,
.mgr-root .rz-dialog-side .table > tbody tr:last-child td { border-bottom: 0; }
/* the current row (clicked / arrived-from-edit) — warm yellow, same swap as the tablegrid.
   --bs-table-bg-state must follow the background: bootstrap paints the zebra stripe as an
   inset box-shadow ABOVE the cell background (via --bs-table-bg-type), and only the
   bg-state variable outranks it — the same channel .table-hover itself uses */
.mgr-page-body .table > tbody tr[data-current] td,
.mgr-page-foot .table > tbody tr[data-current] td,
.mgr-root .rz-dialog .table > tbody tr[data-current] td,
.mgr-root .rz-dialog-side .table > tbody tr[data-current] td {
    background: var(--row-hover);
    --bs-table-bg-state: var(--row-hover);
}
.mgr-page-body .table > tbody tr:not([data-current]):hover td,
.mgr-page-foot .table > tbody tr:not([data-current]):hover td,
.mgr-root .rz-dialog .table > tbody tr:not([data-current]):hover td,
.mgr-root .rz-dialog-side .table > tbody tr:not([data-current]):hover td {
    background: var(--ui-blue-soft);
    --bs-table-bg-state: var(--ui-blue-soft);
}

/* --- house tabs — classic folder tabs: gray resting on a line, the active one white and merged
   with the card (moved from 20-mgr 27/07/2026; applies inside the mgr page body) --- */
.mgr-page-body .nav-tabs {
    border-bottom: 1px solid var(--line-strong);
    gap: 0.25rem;
    margin-bottom: 1.25rem;
}
.mgr-page-body .nav-tabs .nav-link {
    border: 1px solid var(--line-strong);
    border-bottom: 0;
    border-radius: 0.5rem 0.5rem 0 0;
    padding: 0.4rem 1.125rem;
    margin-bottom: 0;
    /* tabs recolored 29/07/2026: resting tabs wear the soft gray surface (same family as the
       table header) instead of the blue wash; the active one still opens into the page surface */
    background: var(--ui-bg-soft);
    color: var(--ui-text-soft);
    font-size: var(--text-body);
    font-weight: 600;
    transition: color var(--btn-whoosh), background-color var(--btn-whoosh);
}
.mgr-page-body .nav-tabs .nav-link:hover {
    background: var(--ui-hover);
    color: var(--ui-heading);
}
/* the active tab paints the surface it sits on, so it reads as "open" into the content */
.mgr-page-body .nav-tabs .nav-link.active {
    background: var(--mgr-bg, #fff);
    color: var(--ui-heading);
    margin-bottom: -1px;
    padding-bottom: calc(0.4rem + 1px);
}

/* tab box (30/07/2026): the tabs are the lid of the box — the strip's bottom line is the
   box's top edge, and the pane's sides and bottom connect to it (the content no longer
   floats detached under the tabs). same line color as the tabs, so the frame reads as one */
.mgr-page-body .nav-tabs:has(+ .tab-box) { margin-bottom: 0; }
.mgr-page-body .tab-box {
    padding: 1.25rem;
    border: 1px solid var(--line-strong);
    border-top: 0;
    border-radius: 0 0 0.5rem 0.5rem;
}
/* the --box active-tab override retired 29/07/2026 with the box itself — the fallback above (--mgr-bg) is the one rule */

/* gal-code* and policy-split moved to 40-catalog.css 30/07/2026 — catalog-only selectors
   have no business loading on every public page */

/* --- the house tooltip — a light bubble for any [data-tip] element (delegated in 03-mgr.js).
   white default (chosen 27/08/2026); a data-tip-style="x" attribute may swap the --tip-* vars --- */
.ibook-tip {
    position: fixed;
    z-index: 1100;
    max-width: 20rem;
    padding: 0.375rem 0.625rem;
    border: 1px solid var(--tip-border, #c9ced6);
    border-radius: 0.375rem;
    background: var(--tip-bg, #ffffff);
    color: var(--tip-color, #212529);
    font-size: 0.8125rem;
    line-height: 1.5;
    text-align: start;
    pointer-events: none;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
    animation: ibook-tip-in var(--btn-whoosh);
}
@keyframes ibook-tip-in {
    from { opacity: 0; }
    to { opacity: 1; }
}
/* the little arrow: under the bubble by default, above it when the tip flips below the element.
   two stacked triangles — ::before draws the 1px border rim, ::after fills with the bubble bg —
   so a light bubble keeps a visible arrow on a light page */
.ibook-tip::before {
    content: "";
    position: absolute;
    top: 100%;
    left: 50%;
    margin-inline-start: -7px;
    border: 7px solid transparent;
    border-top-color: var(--tip-border, #c9ced6);
}
.ibook-tip::after {
    content: "";
    position: absolute;
    top: 100%;
    left: 50%;
    margin-inline-start: -6px;
    border: 6px solid transparent;
    border-top-color: var(--tip-bg, #ffffff);
}
.ibook-tip.ibook-tip--below::before {
    top: auto;
    bottom: 100%;
    border-top-color: transparent;
    border-bottom-color: var(--tip-border, #c9ced6);
}
.ibook-tip.ibook-tip--below::after {
    top: auto;
    bottom: 100%;
    border-top-color: transparent;
    border-bottom-color: var(--tip-bg, #ffffff);
}

/* --- gf.Flicker — 5 quick highlight blinks over 2s ("something changed right here") --- */
@keyframes ibook-flicker {
    0%, 100% { background-color: transparent; }
    50% { background-color: var(--row-hover, #fdf6dd); }
}
.ibook-flicker { animation: ibook-flicker 0.4s ease-in-out 5; }

/* --- image picker — visual file chooser for a fixed wwwroot folder --- */
.imgpick { position: relative; }
.imgpick__trigger {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    min-height: calc(var(--ui-control-h) * 0.82);
    padding: 0.25rem 0.625rem;
    border: 1px solid var(--field-border);
    border-radius: var(--field-radius);
    background: var(--field-bg);
    color: var(--ui-deep);
    font-size: 1rem;
    cursor: pointer;
    transition: border-color var(--ui-fast), background-color var(--ui-fast);
}
/* same field behavior as every input: soft hint on hover, blue border on focus */
.imgpick__trigger:hover { background: var(--field-bg-hover); }
.imgpick__trigger:focus-visible {
    outline: none;
    background: var(--field-bg);
    border-color: var(--field-border-focus);
    box-shadow: var(--field-glow);
}
.imgpick__trigger > i { margin-inline-start: auto; color: var(--ui-text-soft); }
.imgpick__thumb {
    height: 24px;
    width: 42px;
    object-fit: cover;
    border-radius: 0.375rem;
    flex: 0 0 auto;
}
.imgpick__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    direction: ltr;
}
.imgpick__name--empty { color: var(--ui-text-faint); }
.imgpick__panel {
    position: absolute;
    z-index: 30;
    inset-inline-start: 0;
    top: calc(100% + 6px);
    width: min(34rem, 90vw);
    max-height: 21rem;
    overflow-y: auto;
    display: block;
    padding: 0.625rem;
    background: #fff;
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius-md);
    box-shadow: var(--ui-shadow-md);
}
.imgpick__panel.is-flipped {
    inset-inline-start: auto;
    inset-inline-end: 0;
}
.imgpick__item {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.375rem;
    border: 2px solid transparent;
    border-radius: 0.5rem;
    background: transparent;
    cursor: pointer;
}
.imgpick__item:hover { background: var(--ui-bg-soft); }
.imgpick__item.is-selected { border-color: var(--ui-blue); }
.imgpick__item img {
    width: 100%;
    height: 64px;
    object-fit: cover;
    border-radius: 0.375rem;
}
.imgpick__item span {
    font-size: 0.75rem;
    color: var(--ui-text-soft);
    direction: ltr;
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.imgpick__item--none { align-items: center; justify-content: center; min-height: 5rem; }
.imgpick__crumb {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0 0 0.5rem;
    border-bottom: 1px solid var(--ui-frame);
    margin-bottom: 0.5rem;
    font-size: 0.8125rem;
    color: var(--ui-text-soft);
    direction: ltr;
    justify-content: flex-end;
}
.imgpick__up {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius-sm);
    background: #fff;
    color: var(--ui-heading);
    font-size: 0.8125rem;
    padding: 0.125rem 0.5rem;
    cursor: pointer;
    direction: rtl;
}
.imgpick__up:hover { background: var(--ui-bg-soft); }
.imgpick__grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.5rem;
}
/* desktop (13/08/2026): a roomier picker — five thumbs a row, taller panel, bigger previews */
@media (min-width: 992px) {
    .imgpick__panel {
        width: min(44rem, 90vw);
        max-height: 60vh;
    }
    .imgpick__grid { grid-template-columns: repeat(5, 1fr); }
    .imgpick__item img { height: 96px; }
}
.imgpick__item--dir {
    align-items: center;
    justify-content: center;
    min-height: 5rem;
    background: var(--ui-bg-soft);
}
.imgpick__item--dir > i { font-size: 1.5rem; color: var(--ui-text-soft); }
.imgpick__hint {
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--ui-frame);
    font-size: 0.75rem;
    color: var(--ui-text-faint);
    text-align: center;
}

/* reduced motion — ONE blanket rule for the whole system (decided 08/08/2026; replaced the
   per-selector list that lived in 20-mgr). users who set "reduce motion" in their OS get every
   animation/transition collapsed to a near-zero duration. NOT `none`: end events must still
   fire for any JS that waits on them. the !important here is the point — this rule must beat
   every animation ever written, present and future. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        transition-delay: 0s !important;
        scroll-behavior: auto !important;
    }
}

/* ============================================================
   shared identity elements — pulled from psycho's public nav section (22/08/2026):
   the avatar circle + the count pill are used by the mgr topbar (and later the public nav)
   ============================================================ */
.user-avatar {
    border: 1px solid var(--line-strongX3);
    border-radius: 50%;
    background: var(--purple);
    color: var(--ink);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
}
.cart-count {
    position: absolute;
    min-width: 18px;
    height: 18px;
    padding: 0 4px;
    border-radius: 999px;
    background: var(--yellow);
    border: 1px solid var(--line-strong);
    color: var(--ink);
    font-weight: 800;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

/* ============================================================
   breadcrumbs — pulled from psycho's page-envelope section (22/08/2026):
   the crumbs trail serves the mgr envelope too, not only the public pages
   ============================================================ */
/* ---------------------------------------------------------------- 1. breadcrumb ---- */
/* page head rhythm: every block spaces DOWNWARD only (crumbs 18, hero 22, h1 26) */
.crumbs {
    max-width: var(--container);
    margin-inline: auto;
    padding: 18px var(--section-px) 18px;
    font-size: var(--text-sm);
    color: var(--muted);
}
.crumbs__list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.crumbs__item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.crumbs__item + .crumbs__item::before {
    font-family: "Font Awesome 6 Free";
    font-weight: 900;
    content: "\f104";
    color: var(--dot-inactive);
    font-size: 0.8rem;
    line-height: 1;
}
.crumbs__link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--muted);
    font-weight: 600;
    transition: color .15s;
}
.crumbs__link:hover { color: var(--teal); }
.crumbs__home i { font-size: 0.95rem; }
.crumbs__current {
    color: var(--ink);
    font-weight: 700;
    max-width: 60vw;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (min-width: 1200px) {
    .crumbs { font-size: 1rem; padding-top: 22px; }
}

/* ============================================================
   THE focus — one bare rule conquers every field everywhere (dialogs included),
   riding the two focus tokens. restored from psycho 23/08/2026: the extraction
   skipped it, so bootstrap's own 4px halo was showing through.
   ibook refinement: a crisp 1px ring instead of a wide soft glow — thin and clear.
   bootstrap's .form-control:focus is matched at equal specificity and loses by load order.
   ============================================================ */
input:focus,
select:focus,
textarea:focus,
.form-control:focus,
.form-select:focus {
    outline: none;
    border-color: var(--focus-border);
    box-shadow: var(--focus-glow);
}

input.is-invalid:focus,
select.is-invalid:focus,
textarea.is-invalid:focus,
.form-control.is-invalid:focus,
input.invalid:focus,
select.invalid:focus,
textarea.invalid:focus,
.form-control.invalid:focus,
.form-select.invalid:focus {
    border-color: var(--focus-border-danger);
    box-shadow: var(--focus-glow-danger);
}

/* ============================================================
   autofill neutralizer (26/08/2026): the browser paints saved-login fields itself —
   yellow in firefox, light blue in chrome — overriding the field skin. that internal
   paint is background-color only, so an inset shadow covers it; the text color needs
   -webkit-text-fill-color because chrome forces its own text color too.
   ============================================================ */
input:autofill {
    box-shadow: inset 0 0 0 1000px var(--field-bg);
    -webkit-text-fill-color: var(--ink);
    caret-color: var(--ink);
}

input:autofill:hover {
    box-shadow: inset 0 0 0 1000px var(--field-bg-hover);
}

input:autofill:focus {
    box-shadow: var(--focus-glow), inset 0 0 0 1000px var(--field-bg);
}

/* form section title (ibook 23/08/2026): the quietest section marker — small bold text with
   a rule running across the rest of the row. for grouping fields inside ONE form, where the
   framed .app-fieldset would be too heavy a container. */
.app-form-section {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    margin: 1.75rem 0 0.875rem;
    padding: 0;
    color: var(--ink);
    font-family: var(--font);
    font-size: 0.8125rem;
    font-weight: 700;
    line-height: 1;
}

/* the line crosses the row on BOTH sides of the label — the same reading as the mgr menu
   divider, so a section title looks the same wherever it appears */
.app-form-section::before,
.app-form-section::after {
    content: "";
    flex: 1;
    border-top: 1px solid var(--ui-border);
}

.app-form-box > fieldset:first-of-type > .app-form-section { margin-top: 0; }

/* copy-on-label (ported from the legacy planner, 23/08/2026): clicking a field's LABEL copies
   the field's value. the copy cursor is what makes it discoverable — nothing else marks it. */
.app-form label.app-label-copy { cursor: copy; }
.app-form label.app-label-copy:hover { color: var(--link); }

/* number fields: no native spinners anywhere — twins the radzen no-spinners decision.
   tiny arrows on narrow numeric fields are noise; typing is the input.
   restored from psycho 23/08/2026 (the same extraction gap that dropped THE focus). */
input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* ============================================================
   mobile size layer (31/08/2026) — Google/Material minimums on phones:
   16px text (also kills the iOS focus auto-zoom), 44-48px touch targets.
   TOKENS FIRST; desktop above 768px stays untouched. Must stay LAST in
   this file — the overrides win by load order at equal specificity.
   ============================================================ */
@media (max-width: 767.98px) {
    :root {
        --ui-control-h: 2.75rem;       /* 44px — topbar icon button, radzen controls */
        --field-font-size: 1rem;       /* 16px — below this iOS zooms every field on focus */
        --field-padding-y: 0.5625rem;  /* lifts field height to 44px */
    }
    .btn { height: 2.75rem; }                            /* 44px */
    .btn-lg { height: 3rem; }                            /* 48px */
    .btn-sm { height: 2.5rem; font-size: 0.9375rem; }    /* 40px */
    /* dense-toolbar sizes — table rows cap them below 44 by design, but never tiny */
    .btn-xs { height: 2.25rem; font-size: 0.875rem; }    /* 36px */
    .btn-xxs { height: 2rem; font-size: 0.8125rem; }     /* 32px */
    .app-form .form-check-input { font-size: 1.25rem; }  /* 20px box — a real thumb target */
    /* house tables: ~48px rows and legible headers */
    .mgr-page-body .table > tbody td,
    .mgr-page-foot .table > tbody td,
    .mgr-root .rz-dialog .table > tbody td,
    .mgr-root .rz-dialog-side .table > tbody td { padding-block: 0.75rem; }
    .mgr-page-body .table > thead th,
    .mgr-page-foot .table > thead th,
    .mgr-root .rz-dialog .table > thead th { font-size: 0.9375rem; }
}
