/*
 * The old HAYA.CMS control panel's face, carried onto the platform shell
 * (ADR 0004, lane CMS-L1).
 *
 * Two jobs. The @font-face block below names the family the theme asks for,
 * and the overrides after it close the geometry gaps the theme has no token
 * for. Everything the theme *can* express -- palette, radii, type size --
 * lives in CmsAdminTheme instead of here, so this file stays as short as the
 * difference actually is.
 *
 * Sizes are written in px on purpose. The shell puts the theme's base size on
 * <html> and lays itself out in rem, so its 16rem sidebar is 224px at our
 * 14px base; px keeps these values directly comparable with the old panel's
 * stylesheet, which is what they are copied from.
 */

/* Weights are the old panel's mapping, not the usual one: regular is 300 and
   400 is Medium (assets/css/style.css). Body text therefore lands on Medium
   exactly as it did there. The old sheet also pulled the FaNum (Persian
   numeral) cuts for 400 and 600 and plain cuts for the rest; the plain cuts
   are used throughout here, because a dashboard shows ids, versions and SQL,
   and which digits a number is written in belongs to .NET's culture
   formatting, not to the font file. */
@font-face {
    font-family: IRANYekanX;
    font-style: normal;
    font-weight: 200;
    src: url('../fonts/IRANYekanX-Light.woff2') format('woff2');
    font-display: swap;
}

@font-face {
    font-family: IRANYekanX;
    font-style: normal;
    font-weight: 300;
    src: url('../fonts/IRANYekanX-Regular.woff2') format('woff2');
    font-display: swap;
}

@font-face {
    font-family: IRANYekanX;
    font-style: normal;
    font-weight: 400;
    src: url('../fonts/IRANYekanX-Medium.woff2') format('woff2');
    font-display: swap;
}

@font-face {
    font-family: IRANYekanX;
    font-style: normal;
    font-weight: 600;
    src: url('../fonts/IRANYekanX-DemiBold.woff2') format('woff2');
    font-display: swap;
}

@font-face {
    font-family: IRANYekanX;
    font-style: normal;
    font-weight: 800;
    src: url('../fonts/IRANYekanX-Bold.woff2') format('woff2');
    font-display: swap;
}

/* The self-hosted emoji face in front of the theme's family (emoji.css):
   its unicode-range confines it to emoji, so --haya-font-family still sets
   every letter. The shell's own body rule is unlayered and this file loads
   after it. */
body {
    font-family: "Haya Emoji", var(--haya-font-family);
}

:root {
    /* 300px in the old panel: adminStyles.css sizes the content as
       calc(100% - 300px) from 881px up. */
    --cms-sidebar: 300px;
    --cms-content-width: 1368px;
    --cms-card-shadow: 0 3px 10px rgba(0, 0, 1, 0.08);
}

body {
    /* style.css:243 -- the old panel read looser than the shell's default. */
    line-height: 1.7;
}

/* Only where the shell actually docks the sidebar. Unscoped, this rule sits
   after the shell's own `max-width: 60rem` block and wins on equal specificity,
   which put a 300px column back on a phone and pushed the page off screen. */
@media (min-width: 60.001rem) {
    .haya-shell {
        grid-template-columns: var(--cms-sidebar) 1fr;
    }
}

/* The drawer keeps the same width as the docked sidebar, the way the old
   panel's sidebar-rtl-open did — but never so wide on a phone that the page
   behind it disappears and the scrim has nothing left to tap. */
@media (max-width: 60rem) {
    .haya-shell__sidebar {
        inline-size: min(var(--cms-sidebar), 85vw);
    }
}

/* Selects size to their content wherever the header is crowded — the shell's
   own rule stretches them to the full row, which is what let flex crush the
   switcher rather than the empty space around it. */
@media (max-width: 60rem) {
    .haya-shell__topbar .haya-select,
    .haya-shell__topbar .haya-select-box {
        inline-size: auto;
        max-inline-size: 10rem;
    }
}

/* Below roughly 420px the controls stop fitting on one line at all. The spacer
   becomes the line break, so the menu button keeps the first line and the rest
   share the second, instead of the switcher shrinking to "pha". */
@media (max-width: 30rem) {
    .haya-shell__topbar {
        flex-wrap: wrap;
        row-gap: 0.5rem;
        column-gap: 0.375rem;
    }

    .haya-shell__topbar .haya-spacer {
        flex-basis: 100%;
    }

    /* The signed-in name goes, its icon stays. Of the two identities in this
       header only one is dangerous to mistake: there is a single account
       signed in, and any number of sites to be editing the wrong one of. */
    .haya-shell__topbar .haya-row.haya-muted > span {
        display: none;
    }
}

.haya-shell__content {
    max-inline-size: var(--cms-content-width);
}

/* The old .card: no border, a soft drop shadow, and the 16px corner that
   arrives here as the theme's large radius (style.css:248). */
.haya-card {
    border-color: transparent;
    box-shadow: var(--cms-card-shadow);
}

/* ------------------------------------------------- collapsible menu (CMS-L1-5)
   Groups closed until asked for, like the old panel's accordion. The markup is
   CmsAdminSidebar's; the shell's own .haya-nav__item styling is reused for the
   entries, so only what differs — rhythm, the group header and its panel, and
   the tree lines — is described here. Everything is scoped to .cms-nav so the
   shell's other menus (the user menu, the command palette) are untouched. */

.cms-nav {
    --cms-nav-duration: 200ms;
    --cms-nav-easing: cubic-bezier(0.2, 0, 0, 1);
    /* Where the child column starts, measured from the group's edge: under
       the centre of the header's text, which is where the old panel hung its
       hairline. The branches are drawn from this same number. */
    --cms-nav-indent: 0.875rem;
    --cms-nav-branch: 0.75rem;
    --cms-nav-gap: 0.1875rem;
    --cms-nav-elbow: 0.375rem;
    --cms-nav-line: var(--haya-border);
    --cms-nav-line-active: color-mix(in srgb, var(--haya-brand) 55%, var(--haya-border));
    --cms-nav-line-hover: color-mix(in srgb, var(--haya-text-muted) 40%, var(--haya-border));
    padding: 0.5rem 0.625rem;
    gap: 0.2rem;
    /* The product's body sets 1.7 for the page; a menu row reads as a label,
       not a paragraph, and that leading made every row taller than its text. */
    line-height: 1.4;
}

.cms-nav .haya-nav__item {
    gap: 0.5rem;
    padding: 0.5rem 0.5625rem;
    transition: background-color 120ms ease, color 120ms ease, padding-inline-start 160ms var(--cms-nav-easing);
}

.cms-nav__group + .cms-nav__group {
    margin-block-start: 1px;
}

.cms-nav__summary {
    inline-size: 100%;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.8rem 0.5625rem;
    border: 0;
    border-radius: var(--haya-radius);
    background: transparent;
    color: var(--haya-text-muted);
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.4;
    text-align: start;
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
}

.cms-nav__summary:hover {
    background: var(--haya-surface-muted);
    color: var(--haya-text);
}

/* The group that holds the current screen says so on its header, open or
   closed — a folded group is where the highlighted entry went, and the header
   is the only thing left on screen to say that. Colour alone, no fill: the
   fill is the entry's, and two filled rows read as two active screens. */
.cms-nav__summary--active {
    color: var(--haya-brand);
}

.cms-nav__summary-text {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Menu glyphs from the old panel's icon font (CmsIcon). Sized and aligned like
   the shell's own SVG icons so a name the font has no glyph for can fall back
   to those without the row moving. */
/* inline-block rather than flex, so a two-tone glyph — two inline layers the
   font's own sheet pulls over each other with a negative margin — would still
   draw correctly if one is ever mapped. A flex box lays those layers out side
   by side instead, which puts half the house next to the other half. */
.cms-icon {
    inline-size: 1.125rem;
    block-size: 1.125rem;
    flex: none;
    display: inline-block;
    font-size: 1.125rem;
    line-height: 1;
}

/* Lucide, drawn as a mask in the current colour (CmsLucideIcon): one set
   for the whole menu, so headers, entries and the tools read as one hand.
   The file is a product asset under _content; the names are held to the
   shipped set by a test, because a mask that 404s draws nothing. */
.cms-lucide {
    flex: none;
    display: inline-block;
    inline-size: 1.125rem;
    block-size: 1.125rem;
    background-color: currentColor;
    -webkit-mask: var(--cms-lucide) center / contain no-repeat;
    mask: var(--cms-lucide) center / contain no-repeat;
}

.cms-nav__items .cms-icon,
.cms-nav__items .cms-lucide,
.cms-nav__items .haya-nav__icon {
    --haya-icon-size: 1rem;
    inline-size: 1rem;
    block-size: 1rem;
    font-size: 1rem;
}

/* An entry whose glyph would repeat a sibling's shows none, and keeps the
   space, so the labels of a group still start on one line. */
.cms-nav__no-icon {
    inline-size: 1rem;
    block-size: 1rem;
    flex: none;
}

.cms-nav__summary .cms-icon,
.cms-nav__summary .cms-lucide,
.cms-nav__summary .haya-nav__icon {
    color: var(--haya-text-muted);
    transition: color 120ms ease;
}

.cms-nav__summary:hover .cms-icon,
.cms-nav__summary:hover .cms-lucide,
.cms-nav__summary:hover .haya-nav__icon,
.cms-nav__summary--active .cms-icon,
.cms-nav__summary--active .cms-lucide,
.cms-nav__summary--active .haya-nav__icon {
    color: inherit;
}

/* The row under the brand: a box that narrows the menu as you type, and a
   button that folds every group. Outside the scrolling <nav>, so both stay
   put however long the menu is. The input has no border of its own; the row
   is one quiet field with the glyph inside it, the way the shell's search
   field in the top bar reads. */
.cms-nav__tools {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.6rem 0.5rem;
    border-block-end: 1px solid var(--haya-border);
}

/* ---- CmsSearchField: the admin's one search box

   A glyph, the input and a clear button in one quiet frame; the input has no
   border of its own. No flex sizing here: a column parent would grow it along
   the block axis from a zero basis and collapse it to its text (the settings
   hub did exactly that). Width and placement come from the caller's Class. */
.cms-search {
    box-sizing: border-box;
    min-inline-size: 0;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    block-size: 2.125rem;
    padding-inline: 0.625rem 0.375rem;
    border: 1px solid var(--haya-border);
    border-radius: var(--haya-radius);
    background: var(--haya-surface-muted);
    color: var(--haya-text-muted);
    transition: border-color 120ms ease, background-color 120ms ease, box-shadow 120ms ease;
}

.cms-search:focus-within {
    border-color: var(--haya-brand);
    background: var(--haya-surface);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--haya-brand) 14%, transparent);
}

.cms-search .cms-search__glyph {
    flex: none;
    inline-size: 1rem;
    block-size: 1rem;
}

/* The shell's .haya-input, unboxed: the frame above is the box. */
.cms-search .cms-search__input {
    flex: 1;
    min-inline-size: 0;
    inline-size: auto;
    block-size: auto;
    min-block-size: 0;
    margin: 0;
    border: 0;
    padding: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    color: var(--haya-text);
    font: inherit;
    font-size: 0.8125rem;
    line-height: 1.4;
    outline: none;
}

.cms-search .cms-search__input:focus,
.cms-search .cms-search__input:focus-visible {
    border: 0;
    box-shadow: none;
    outline: none;
}

.cms-search .cms-search__input::placeholder {
    color: var(--haya-text-muted);
}

/* The browser's own clear control is replaced by ours, so it matches on every
   engine and sits where RTL puts it. */
.cms-search .cms-search__input::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
}

.cms-search__clear {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 1.5rem;
    block-size: 1.5rem;
    padding: 0;
    border: 0;
    border-radius: var(--haya-radius);
    background: transparent;
    color: var(--haya-text-muted);
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
}

.cms-search__clear:hover {
    background: var(--haya-surface);
    color: var(--haya-text);
}

.cms-search__clear:focus-visible {
    outline: 2px solid var(--haya-brand);
    outline-offset: 1px;
}

.cms-search__clear .cms-lucide {
    inline-size: 0.875rem;
    block-size: 0.875rem;
}

/* Inside a popover list: the same frame, a step smaller. */
.cms-search--compact {
    block-size: 1.875rem;
    padding-inline: 0.5rem 0.25rem;
}

.cms-search--compact .cms-search__input {
    font-size: 0.75rem;
}

/* Placements. */
.cms-nav__search {
    flex: 1;
}

/* One field and one quiet icon, not two boxes: the fold button has no edge
   of its own until the pointer asks for it. */
.cms-nav__tool {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2.125rem;
    block-size: 2.125rem;
    padding: 0;
    border: 0;
    border-radius: var(--haya-radius);
    background: transparent;
    color: var(--haya-text-muted);
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
}

.cms-nav__tool:hover {
    background: var(--haya-surface-muted);
    color: var(--haya-text);
}

.cms-nav__tool:focus-visible {
    outline: 2px solid var(--haya-brand);
    outline-offset: 1px;
}

.cms-nav__tool .cms-lucide {
    inline-size: 1rem;
    block-size: 1rem;
}

/* Nothing left after filtering: said in the menu's own voice, not as an error. */
.cms-nav__empty {
    padding: 1rem 0.625rem;
    color: var(--haya-text-muted);
    font-size: 0.8125rem;
    text-align: center;
}

/* Points down when open, and toward the text — that is, the way the reading
   direction runs — when closed. Same clock as the panel below it, so the arrow
   lands exactly when the rows do. */
.cms-nav__chevron {
    inline-size: 1rem;
    block-size: 1rem;
    transform: rotate(-90deg);
    transition: transform var(--cms-nav-duration) var(--cms-nav-easing);
}

[dir="rtl"] .cms-nav__chevron {
    transform: rotate(90deg);
}

.cms-nav__chevron--open,
[dir="rtl"] .cms-nav__chevron--open {
    transform: rotate(0deg);
}

/* The panel is a one-row grid whose row goes from 0fr to 1fr: height follows
   the content without being measured, so there is no script and no jump. The
   rows stay in the DOM either way (the component never re-renders them for a
   toggle); visibility:hidden takes the closed panel's links out of the tab
   order and out of the accessibility tree, and is delayed on the way shut so
   the rows are still visible while they fold. */
.cms-nav__panel {
    display: grid;
    grid-template-rows: 0fr;
    opacity: 0;
    visibility: hidden;
    transition:
        grid-template-rows var(--cms-nav-duration) var(--cms-nav-easing),
        opacity var(--cms-nav-duration) ease,
        visibility 0s linear var(--cms-nav-duration);
}

.cms-nav__panel--open {
    grid-template-rows: 1fr;
    opacity: 1;
    visibility: visible;
    transition-delay: 0s;
}

@media (prefers-reduced-motion: reduce) {
    .cms-nav__chevron,
    .cms-nav__panel,
    .cms-nav__summary,
    .cms-nav__items,
    .cms-nav .haya-nav__item {
        transition: none;
    }
}

/* The child column. Clipped so the fold does not spill, with a margin so a
   focused link's ring is not cut; the tree lines sit in the start padding,
   which is inside the clip. */
.cms-nav__items {
    min-block-size: 0;
    overflow: hidden;
    overflow: clip;
    overflow-clip-margin: 0.25rem;
    display: flex;
    flex-direction: column;
    gap: var(--cms-nav-gap);
    padding-block: 0.1875rem 0.375rem;
    padding-inline-start: var(--cms-nav-indent);
    margin-inline-start: var(--cms-nav-indent);
    transition: padding-block var(--cms-nav-duration) var(--cms-nav-easing);
}

/* A 0fr row still has to hold its item's padding — min-block-size:0 lets the
   content shrink, not the box around it — so a closed group would keep a
   5px sliver of empty column under its header. The padding folds with the
   rows instead, on the same clock. */
.cms-nav__panel:not(.cms-nav__panel--open) .cms-nav__items {
    padding-block: 0;
}

/* The tree. Each row draws its own stretch of the trunk (::before) and its
   branch (::after) in the column's start padding, so the trunk is exactly as
   long as the rows it joins: it starts at the first row and ends at the centre
   of the last, where the last branch leaves it. Logical insets, so in RTL the
   trunk is on the right and the branches run leftwards into the rows. */
.cms-nav__items .haya-nav__item {
    position: relative;
}

.cms-nav__items .haya-nav__item::before,
.cms-nav__items .haya-nav__item::after {
    content: "";
    position: absolute;
    inset-inline-start: calc(-1 * var(--cms-nav-indent));
    pointer-events: none;
}

.cms-nav__items .haya-nav__item::before {
    inset-block: 0;
    border-inline-start: 1px solid var(--cms-nav-line);
    transition: border-color 160ms ease;
}

/* Reaches up over the gap above it (or the column's top padding, for the
   first row) so the trunk is one unbroken line. */
.cms-nav__items .haya-nav__item::before {
    inset-block-start: calc(-1 * var(--cms-nav-gap));
}

.cms-nav__items .haya-nav__item:first-child::before {
    inset-block-start: -0.1875rem;
}

/* Stops where the last elbow's curve begins, so the two meet as one line. */
.cms-nav__items .haya-nav__item:last-child::before {
    inset-block-end: calc(50% + var(--cms-nav-elbow));
}

/* The branch is an elbow, not a tick: it leaves the trunk with a small
   curve and runs level into the row's centre. Its upright leg sits on the
   trunk, so only the curve and the level run read as new line. */
.cms-nav__items .haya-nav__item::after {
    inset-block-start: 0;
    block-size: 50%;
    inline-size: var(--cms-nav-branch);
    border-inline-start: 1px solid var(--cms-nav-line);
    border-block-end: 1px solid var(--cms-nav-line);
    border-end-start-radius: var(--cms-nav-elbow);
    transition: border-color 160ms ease;
}

/* The whole tree comes forward a shade while the pointer is in its group,
   and a child row nudges toward its branch — the line is where it came from. */
.cms-nav__group:hover .haya-nav__item::before,
.cms-nav__group:hover .haya-nav__item::after {
    border-color: var(--cms-nav-line-hover);
}

.cms-nav__items .haya-nav__item:hover {
    padding-inline-start: 0.75rem;
}

/* The branch to the current screen is the one line in the tree that carries
   information, so it alone takes the brand — softened, so it reads as a
   pointer and not a second highlight. */
.cms-nav__items .haya-nav__item--active::after,
.cms-nav__group:hover .haya-nav__item--active::after {
    border-color: var(--cms-nav-line-active);
}

/* The active child's icon takes the brand with the text, so the row reads
   as one coloured thing rather than a coloured label beside a grey glyph. */
.cms-nav__items .haya-nav__item--active .cms-icon,
.cms-nav__items .haya-nav__item--active .cms-lucide {
    color: var(--haya-brand);
}

/* The settlement panel on the seller's invoice screen. Boxed off from the
   figures above it because it is the one place on that page where a click
   changes money. */
.cms-settle {
    margin-block-start: 1rem;
    padding-block-start: 1rem;
    border-block-start: 1px solid var(--haya-border);
}

.cms-settle__actions {
    display: flex;
    gap: 0.5rem;
    margin-block-start: 1rem;
}

/* The invoice and report screens' field lists. The markup said `haya-dl` from
   the start, but no stylesheet — the shell's or ours — ever defined it, so the
   browser fell back to a bare <dl>: label on one line, value indented under
   it, and the card read as loose text. Defined here because the classes are
   this product's markup; the platform never shipped them (the same trap its
   own tenant-detail page fell into). */
.haya-dl {
    display: grid;
    grid-template-columns: max-content 1fr;
    column-gap: 1.25rem;
    row-gap: 0;
    margin: 0;
}

.haya-dl dt {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--haya-text-muted);
    padding-block: 0.5rem;
}

.haya-dl dd {
    margin: 0;
    padding-block: 0.5rem;
    font-variant-numeric: tabular-nums;
    /* A grid cell refuses to shrink below its content, and a buyer's subject
       key is one long unbreakable token — without these two the value column
       pushes past the card's edge and is clipped by its overflow. */
    min-width: 0;
    overflow-wrap: anywhere;
}

/* A hairline between rows, not after the last: dt and dd sit on the same grid
   row, so the border goes on both and starts from the second row. */
.haya-dl dt:not(:first-of-type),
.haya-dl dd:not(:first-of-type) {
    border-block-start: 1px solid var(--haya-border);
}

/* Two cards side by side on the invoice screen, stacked on a narrow pane. */
.haya-grid--2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (max-width: 60rem) {
    .haya-grid--2 {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* CMS-L31-7: the shell spaces cards with `.haya-card + .haya-card`, and a
   screen that puts a dialog host between two cards defeats it — the tenant
   screen's add-member dialog sits between Members and Provisioning, so the
   two touched and read as one card. A dialog host takes no room, so a card
   after one is spaced as if it followed the card before it. The shell's rule
   is the platform's to fix; this holds until it looks past hidden siblings. */
.haya-card ~ .haya-dialog-host + .haya-card {
    margin-block-start: 1rem;
}

/* The report's cards follow a stat grid, which the shell's own
   `.haya-card + .haya-card` rule cannot see across. */
.cms-report__card {
    margin-block-start: 1rem;
}

/* The report's stat row. Explicit columns rather than the shell's auto-fit:
   with four cards, auto-fit at typical widths packs three and wraps the
   fourth into a lonely second row. Two-by-two reads as one block, and the
   four-up row comes back only where all four genuinely fit — the revenue
   card's "15,500,000 IRR" needs the room. */
.cms-report__stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 96rem) {
    .cms-report__stats {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

@media (max-width: 40rem) {
    .cms-report__stats {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* A date or an amount split over two lines reads as two rows. The tables
   already scroll inside their card, so keeping these on one line costs a
   scrollbar at worst, never an overflowing page. */
.cms-cell--keep {
    white-space: nowrap;
}

/* The short form of a subject key (see SubjectKey.razor). LTR as a token:
   an account id is not prose, and the full key sits in the title. */
.cms-subject {
    direction: ltr;
    unicode-bidi: isolate;
}

/* A pattern rather than prose: an invoice prefix shown as "WO-#####". In a
   Persian page the hyphen is neutral and the run comes out reordered as
   "#####-WO", which the browser pass caught on the sellers desk — the same
   trap the stats row met with "0 IRR".
   plaintext rather than an LTR isolate: this is a block, and forcing its
   direction would also drag it to the left edge of a right-aligned cell.
   Letting the line order itself by its own first strong character fixes the
   reading without moving the box. */
.cms-pattern {
    unicode-bidi: plaintext;
    text-align: match-parent;
}

/* English figures inside a Persian page. A line that starts with a digit
   takes the paragraph's direction, so "0 IRR" and "3 overdue · …" come out
   reordered ("IRR 0", "overdue · … 3"). plaintext lets each line order itself
   by its own first strong character — Persian lines stay Persian — and
   match-parent keeps the alignment where the card put it. */
.haya-stat__value,
.haya-stat__hint,
.haya-dl dd {
    unicode-bidi: plaintext;
    text-align: match-parent;
}

/* A box of code an operator types: robots.txt rules, and whatever comes next.
   Monospaced and left to right whatever the panel's language is, because
   every line of it is an ASCII keyword and a path — a Persian page would
   otherwise reorder "Disallow: /private" on screen into something nobody can
   proofread (CMS-L17-6). */
.cms-code {
    font-family: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, monospace;
    font-size: 13px;
    line-height: 1.8;
    direction: ltr;
    text-align: left;
    white-space: pre;
    overflow-x: auto;
}

/* ── the AI credit screen (CMS-L23) ──────────────────────────────────────────
 *
 * One number leads. A balance is the thing the operator came for, so it is the
 * only display-size figure on the screen and everything else steps down from
 * it — the label above is 11px uppercase, the sentence below 13px muted, and
 * the three supporting facts a full tier lower again. Hierarchy from weight
 * and colour before size, which is what keeps a dense screen calm.
 */

.cms-credit {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.cms-credit__headline {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-areas:
        "label flag"
        "figure figure"
        "note note";
    align-items: center;
    gap: 2px 12px;
}

.cms-credit__label {
    grid-area: label;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--haya-text-muted);
}

.cms-credit__figure {
    grid-area: figure;
    font-size: 40px;
    line-height: 1.15;
    font-weight: 600;
    letter-spacing: -0.02em;
    color: var(--haya-text);
    /* A figure that changes must not shift the line under it. */
    font-variant-numeric: tabular-nums;
}

.cms-credit__note {
    grid-area: note;
    font-size: 13px;
    line-height: 1.7;
    color: var(--haya-text-muted);
}

.cms-credit__flag {
    grid-area: flag;
    justify-self: start;
}

/* Two columns of label-over-value, with a rule doing the separating rather
   than a border box. */
.cms-credit__facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 16px 24px;
    margin: 0;
    padding-block-start: 18px;
    border-block-start: 1px solid var(--haya-border);
}

    .cms-credit__facts dt {
        font-size: 12px;
        color: var(--haya-text-muted);
        margin-block-end: 4px;
    }

    .cms-credit__facts dd {
        margin: 0;
        font-size: 16px;
        font-weight: 600;
        color: var(--haya-text);
        font-variant-numeric: tabular-nums;
    }

/* Figures read left to right and sit where their label does.
   The two halves have to be said separately for the reason the result's
   address does: a bidi mode that gets the reading right resolves `start`
   against the digits and throws the figure to the far side of the card, and
   an em-dash — what an account that never bought credit shows — is neutral,
   so it lands wherever the last rule left it. */
.cms-credit__figure,
.cms-credit__facts dd,
.cms-bars__value,
.cms-packs__credits,
.cms-packs__unit {
    direction: ltr;
    unicode-bidi: isolate;
    text-align: left;
}

[dir="rtl"] .cms-credit__figure,
[dir="rtl"] .cms-credit__facts dd,
[dir="rtl"] .cms-bars__value,
[dir="rtl"] .cms-packs__credits,
[dir="rtl"] .cms-packs__unit {
    text-align: right;
}

.cms-credit__split {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 16px;
}

.cms-credit__models {
    width: 100%;
}

/* A number column reads as a column only when its digits line up and it sits
   against the same edge on every row, in both directions. */
.cms-num {
    font-variant-numeric: tabular-nums;
    text-align: end;
    unicode-bidi: plaintext;
    white-space: nowrap;
}

.cms-num--strong {
    font-weight: 600;
    color: var(--haya-text);
}

/* Name, bar, number — the bar carries the comparison and the number carries
   the fact, because neither does both. */
.cms-bars {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

    .cms-bars li {
        display: grid;
        grid-template-columns: minmax(96px, auto) 1fr auto;
        align-items: center;
        gap: 12px;
    }

.cms-bars__name {
    font-size: 13px;
    color: var(--haya-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cms-bars__track {
    height: 6px;
    border-radius: 999px;
    background: var(--haya-surface-muted);
    overflow: hidden;
}

.cms-bars__fill {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: var(--haya-brand, #126fbe);
}

.cms-bars__value {
    font-size: 13px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* The packs, as a price list rather than a row of buy buttons: nothing on
   this screen sells anything (ADR 0007). */
.cms-packs {
    list-style: none;
    margin: 12px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.cms-packs__item {
    display: grid;
    grid-template-columns: 1fr auto auto auto;
    align-items: baseline;
    gap: 16px;
    padding: 10px 0;
    border-block-end: 1px solid var(--haya-border);
}

    .cms-packs__item:last-child {
        border-block-end: none;
    }

.cms-packs__name {
    font-weight: 500;
}

.cms-packs__credits,
.cms-packs__unit {
    font-size: 13px;
    color: var(--haya-text-muted);
    white-space: nowrap;
}

.cms-packs__price {
    font-weight: 600;
    white-space: nowrap;
}

.cms-pager {
    margin-block-start: 12px;
    align-items: center;
}

/* ── the SEO assistant (CMS-L23) ─────────────────────────────────────────────
 *
 * The rows are search results, not table cells. That is the whole idea of the
 * screen: an author judging a description should be looking at the thing a
 * stranger will see, and a missing description should read as a gap rather
 * than as a cross in a column.
 */

.cms-seo-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding-block-end: 12px;
    margin-block-end: 4px;
    border-block-end: 1px solid var(--haya-border);
}

.cms-seo-count {
    text-align: match-parent;
    font-size: 13px;
    color: var(--haya-text-muted);
    unicode-bidi: plaintext;
}

.cms-seo-rows,
.cms-seo-proposals {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
}

.cms-seo-row,
.cms-seo-proposal {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: start;
    gap: 16px;
    padding: 16px 0;
    border-block-end: 1px solid var(--haya-border);
}

    .cms-seo-row:last-child,
    .cms-seo-proposal:last-child {
        border-block-end: none;
    }

/* A page with nothing wrong is still listed — an audit that hides them cannot
   be read as "this is my site" — but it recedes. */
.cms-seo-row--clean .cms-seo-result__title,
.cms-seo-row--clean .cms-seo-result__text {
    opacity: .72;
}

.cms-seo-row__pick,
.cms-seo-proposal__pick {
    display: flex;
    align-items: center;
    /* The checkbox is 16px; the label carries it to a 40px target. */
    min-block-size: 40px;
    min-inline-size: 24px;
    cursor: pointer;
}

.cms-seo-row__findings {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 6px;
    max-inline-size: 320px;
}

.cms-seo-proposal {
    grid-template-columns: auto 1fr;
}

.cms-seo-proposal--failed {
    opacity: .75;
}

.cms-seo-proposal__body {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-inline-size: 0;
}

.cms-seo-proposal__meta,
.cms-seo-proposal__error {
    text-align: match-parent;
    margin: 0;
    font-size: 12px;
    color: var(--haya-text-muted);
    unicode-bidi: plaintext;
}

.cms-seo-proposal__error {
    color: #c8362f;
}

.cms-seo-spend {
    margin: 4px 0 16px;
    font-size: 13px;
    color: var(--haya-text-muted);
}

.cms-seo-warn {
    margin: 12px 0 0;
    font-size: 13px;
    line-height: 1.7;
    color: #9b431d;
}

/* The result itself. Blue title, grey address, dark sentence — the shape every
   search result on the web has, so an author recognises what they are judging
   without being told. */
.cms-seo-result {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-inline-size: 0;
}

/* An address in a Persian result needs two things that pull apart, and the
   browser pass made both visible in turn.
   It has to READ left to right, or the leading slash is reordered to the end
   and /fa/shipping renders as fa/shipping/ — so the element is `ltr` and
   isolated from the text around it.
   It also has to SIT where the result starts, under its own title, or it
   drifts to the far side of the row and stops looking like it belongs to
   anything. `start` cannot give both: with `plaintext` it resolves against
   the LTR run, and `match-parent` just computes to `start` again.
   So the reading direction is fixed on the element and the alignment is
   stated per panel direction, which is the only pair that is true in both. */
.cms-seo-result__url {
    font-size: 12px;
    color: var(--haya-text-muted);
    direction: ltr;
    unicode-bidi: isolate;
    text-align: left;
    overflow-wrap: anywhere;
}

[dir="rtl"] .cms-seo-result__url {
    text-align: right;
}

.cms-seo-result__title {
    font-size: 17px;
    line-height: 1.45;
    color: #1a0dab;
    text-decoration: none;
    overflow-wrap: anywhere;
}

    .cms-seo-result__title:hover {
        text-decoration: underline;
    }

.cms-seo-result__text {
    font-size: 13px;
    line-height: 1.75;
    color: var(--haya-text);
    overflow-wrap: anywhere;
    text-wrap: pretty;
}

/* The gap, made visible. An empty row would read as a rendering fault; this
   reads as an absence, which is what it is. */
.cms-seo-result__text--missing {
    font-style: italic;
    color: var(--haya-text-muted);
    border-inline-start: 2px solid #e5b567;
    padding-inline-start: 10px;
}

/* Editable in place, and styled to stay the result rather than become a form:
   an operator changing one word should not have to look at a different thing
   from the one they were judging. */
.cms-seo-result__title-input,
.cms-seo-result__text-input {
    inline-size: 100%;
    border: 1px solid transparent;
    border-radius: var(--haya-radius);
    padding: 4px 8px;
    margin-inline-start: -8px;
    background: transparent;
    font: inherit;
    color: inherit;
    resize: vertical;
}

.cms-seo-result__title-input {
    font-size: 17px;
    line-height: 1.45;
    color: #1a0dab;
}

.cms-seo-result__text-input {
    font-size: 13px;
    line-height: 1.75;
    color: var(--haya-text);
}

    .cms-seo-result__title-input:hover,
    .cms-seo-result__text-input:hover {
        border-color: var(--haya-border);
    }

    .cms-seo-result__title-input:focus,
    .cms-seo-result__text-input:focus {
        outline: none;
        border-color: var(--haya-brand, #126fbe);
        background: #fff;
    }

    .cms-seo-result__title-input:disabled,
    .cms-seo-result__text-input:disabled {
        color: var(--haya-text-muted);
    }
/* ── The customer desk (CMS-L28) ─────────────────────────────────────────
   Four classes this product's markup invents, defined here rather than left
   to the browser's defaults. That is not a formality: `haya-dl` above exists
   because exactly these four were once written and never defined, on this
   product's invoice screen and on the platform's tenant page, and both
   rendered as a stack of indented text nobody could read. */

/* The filter bar in a card header: a search box and a select, wrapping on a
   narrow panel rather than pushing the card's title off the row. */
.cms-filter-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
}

.cms-filter-row__search {
    flex: 1 1 14rem;
}

/* The shell's inputs are full width, and a card header sizes its actions to
   their content, so the search box and its filter stacked on two lines in a
   header with room for both side by side. The header's action slot says how
   wide it wants to be (a flex basis, which a percentage width inside a
   shrink-to-fit box cannot), and the controls share it. */
.haya-card__header > .haya-row:has(> .cms-filter-row) {
    flex: 0 1 34rem;
    min-width: 0;
}

.cms-filter-row:has(> .haya-input) {
    width: 100%;
}

.cms-filter-row > .haya-input {
    width: auto;
    flex: 1 1 14rem;
    min-width: 0;
}

.cms-filter-row > select.haya-input {
    flex: 0 1 12rem;
}

/* A labelled control in a card body. Column rather than row so the label sits
   above its input in both directions — a right-to-left panel that put them
   side by side would need a mirrored rule for nothing. */
.cms-field {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    margin-block-end: 0.75rem;
    font-size: 0.8125rem;
    color: var(--haya-text-muted);
}

/* Several of those side by side, for the one place that asks for two short
   values and a button at once. */
.cms-field-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    align-items: flex-end;
    margin-block-end: 1rem;
}

.cms-field-row .cms-field {
    flex: 1 1 12rem;
    margin-block-end: 0;
}

/* A customer's saved addresses on the operator's page: read-only, so a list
   rather than the cards the shopper's own page gives them. */
.cms-address-list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.cms-address-list li {
    padding-block-end: 0.75rem;
    border-block-end: 1px solid var(--haya-border);
}

.cms-address-list li:last-child {
    padding-block-end: 0;
    border-block-end: 0;
}

/* A site's languages (CMS-L29-3). One row per language, with the actions
   that apply to it: which is default, where it sits in the picker's order,
   and whether it stays. */
.cms-languages {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin: 0 0 1rem;
    padding: 0;
    list-style: none;
}

.cms-languages__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    padding-block: 0.5rem;
    border-block-end: 1px solid var(--haya-border);
}

.cms-languages__row:last-child {
    border-block-end: 0;
}

/* The language's own name, then its code — which reads left to right whatever
   the panel's language is, and is isolated so its neighbours are not
   reordered around it. */
.cms-languages__name {
    display: inline-flex;
    align-items: baseline;
    gap: 0.5rem;
    min-width: 8rem;
    font-weight: 600;
}

.cms-languages__code {
    color: var(--haya-text-muted);
    font-size: 0.75rem;
    font-weight: 400;
    unicode-bidi: isolate;
}

.cms-languages__count {
    flex: 1;
    color: var(--haya-text-muted);
    font-size: 0.875rem;
}

.cms-languages__add {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-block-start: 1rem;
}

/* A refusal about the form still on screen, rather than a toast that leaves
   nothing to read beside what caused it. */
.cms-form-error {
    margin: 0 0 1rem;
    color: var(--haya-danger, #b42318);
    font-size: 0.875rem;
}

/* ── a site's checkout settings (CMS-L46) ─────────────────────────────── */

.cms-checkout-switches {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-block-start: 12px;
}

.cms-checkout-switch {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
}

/* The fields table widens with the site's languages; it scrolls inside its
   card rather than pushing the page sideways. */
.cms-checkout-table {
    overflow-x: auto;
}

    .cms-checkout-table .haya-input,
    .cms-checkout-table .haya-select {
        min-width: 9rem;
    }
/* The user-fields desk (CMS-L32-8). */
.cms-user-field-form {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.cms-user-field-choices,
.cms-user-field-where {
    margin: 0;
    padding: 0.75rem;
    border: 1px solid var(--haya-border);
    border-radius: 0.5rem;
}

.cms-user-field-choices legend,
.cms-user-field-where legend {
    padding-inline: 0.25rem;
    font-size: 0.8125rem;
    color: var(--haya-text-muted);
}

.cms-user-field-where {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.25rem;
    align-items: center;
}

.cms-user-field-where small {
    flex-basis: 100%;
}

/* A checkbox and its words on one line, in either direction. */
.cms-check {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.875rem;
    cursor: pointer;
}

/* The site's SMS account desk (CMS-L33-3). */
.cms-sms-form {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.cms-sms-balance {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin: 0;
}

.cms-sms-balance strong {
    font-size: 1.25rem;
    unicode-bidi: plaintext;
}

/* ── Theme store desk (CMS-L48-1) ────────────────────────────────────── */

/* A theme's row: its first letter on its own colour, beside its name. */
.cms-theme-row {
    display: flex;
    align-items: center;
    gap: 12px;
}

/* The row's actions on one line: four short buttons stacked two by two read
   as two rows of a table that has one. */
.cms-theme-row__actions {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 0.25rem;
    white-space: nowrap;
}

.cms-theme-row__cover {
    flex: none;
    display: grid;
    place-items: center;
    inline-size: 40px;
    block-size: 40px;
    border-radius: 8px;
    background: linear-gradient(135deg, hsl(var(--ow-hue, 212) 78% 52%) 0%, hsl(calc(var(--ow-hue, 212) + 28) 72% 40%) 100%);
    color: #fff;
    font-size: 18px;
    font-weight: 800;
    line-height: 1;
    user-select: none;
}

/* ----------------------------------------------------- AI resale (CMS-L54) */

/* The tier's one formula, set apart from the prose around it so a reader
   finds "cost → wholesale → customer" before any field. Logical properties
   only: the panel is RTL in Persian and LTR in English. */
.cms-resale__formula {
    margin-block: 0 1rem;
    padding: 0.75rem 1rem;
    border-inline-start: 3px solid var(--haya-brand);
    background: var(--haya-surface-muted);
    border-radius: var(--haya-radius);
    line-height: 1.9;
}

/* The worked example under the markup field; it moves as the field is typed. */
.cms-resale__example {
    margin-block: 0.5rem 0;
    font-weight: 600;
    unicode-bidi: plaintext;
    text-align: start;
}

/* ================================================= the shell, redesigned (CMS-L52)
   Where you are at the head of the sidebar, what you can do in task groups,
   who you are at its foot; the top bar keeps the trail, the palette, the
   language and the appearance menu. Every colour below is a theme token, so
   the same rules read in both schemes. */

/* ---- brand row: the product's mark and the site this session works in */

.cms-brand {
    flex: none;
    display: flex;
    align-items: center;
    gap: 0.625rem;
    box-sizing: border-box;
    block-size: var(--haya-shell-header-height);
    padding-inline: 0.875rem 0.625rem;
    border-block-end: 1px solid var(--haya-border);
}

/* The WebOne mark (78x50), a step larger than the 26px wordmark it replaces:
   it is now the first thing in the reading direction and shares the row with
   the site, so it has to hold its own beside a name. Two files, one per
   scheme: the mark is white ink on a gradient and the light surface gets its
   dark-ink twin, so neither scheme ever shows an invisible logo. */
.cms-brand__logo {
    flex: none;
    inline-size: auto;
    block-size: 26px;
    max-inline-size: 44px;
    border-radius: 0;
}

:root[data-haya-scheme='dark'] .cms-brand__logo--light,
:root:not([data-haya-scheme='dark']) .cms-brand__logo--dark {
    display: none;
}

.cms-brand__home {
    flex: none;
    display: flex;
    align-items: center;
    gap: 0.625rem;
    color: inherit;
    text-decoration: none;
    border-radius: var(--haya-radius);
}

.cms-brand__home:focus-visible {
    outline: 2px solid var(--haya-brand);
    outline-offset: 2px;
}

.cms-brand__mark {
    flex: none;
    display: grid;
    place-items: center;
    inline-size: 2rem;
    block-size: 2rem;
    border-radius: var(--haya-radius);
    background: var(--haya-brand);
    color: var(--haya-brand-contrast);
    font-weight: 700;
}

.cms-brand__name {
    font-weight: 700;
    white-space: nowrap;
}

/* ---- the site switcher: a pill, and the list it opens */

/* The row's remaining width, with the pill sized to its site's name and set
   at the far end — a gap between it and the mark rather than a bar running
   into it. A long name still shrinks and ellipsizes inside the row. */
.cms-tenant {
    flex: 1;
    min-inline-size: 0;
    display: flex;
    justify-content: flex-end;
}

.cms-tenant__pill {
    /* The list anchors to the pill the way the shell's menus anchor to their
       trigger (haya-row-actions__menu). */
    anchor-name: var(--haya-row-actions-anchor);
    inline-size: auto;
    max-inline-size: 100%;
    min-inline-size: 0;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    block-size: calc(38rem / 14);
    padding-block: 0;
    padding-inline: 0.375rem 0.5rem;
    border: 1px solid var(--haya-border);
    border-radius: var(--haya-radius);
    background: var(--haya-surface);
    color: var(--haya-text);
    font: inherit;
    text-align: start;
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease;
}

.cms-tenant__pill:not(.cms-tenant__pill--static):hover,
.cms-tenant__pill:has(+ .cms-pop:popover-open) {
    background: var(--haya-surface-muted);
    border-color: color-mix(in srgb, var(--haya-border) 55%, var(--haya-text-muted));
}

.cms-tenant__pill:focus-visible,
.cms-user__card:focus-visible,
.cms-scheme-seg__btn:focus-visible {
    outline: 2px solid var(--haya-brand);
    outline-offset: 1px;
}

.cms-tenant__pill--static {
    cursor: default;
}

/* While the site's name is read: the pill's outline with two muted bars. */
.cms-tenant__pill--loading .cms-tenant__skeleton {
    background: var(--haya-surface-muted);
    border-radius: 0.375rem;
}

.cms-tenant__skeleton--name {
    inline-size: 3.5rem;
    block-size: 0.625rem;
}

@media (prefers-reduced-motion: no-preference) {
    .cms-tenant__pill--loading .cms-tenant__skeleton {
        animation: cms-tenant-pulse 1.2s ease-in-out infinite alternate;
    }
}

@keyframes cms-tenant-pulse {
    to {
        opacity: 0.45;
    }
}

.cms-tenant__pill:disabled {
    cursor: progress;
    opacity: 0.7;
}

/* A site's monogram: its first letter on a hue derived from its key, the
   rule the owner panel's site cards use (OwnerMonograms). White on a mid
   lightness is legible in either scheme; the hue is what tells sites apart. */
.cms-tenant__mono {
    flex: none;
    display: grid;
    place-items: center;
    inline-size: 1.5rem;
    block-size: 1.5rem;
    border-radius: 0.375rem;
    background: hsl(var(--cms-mono-hue, 212) 46% 44%);
    color: white;
    font-size: 0.75rem;
    font-weight: 700;
    line-height: 1;
}

.cms-tenant__text,
.cms-user__text {
    flex: 1;
    min-inline-size: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 1px;
    line-height: 1.15;
}

.cms-tenant__name,
.cms-user__name {
    font-size: 0.8125rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cms-user__caption {
    font-size: 0.6875rem;
    color: var(--haya-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cms-tenant__chevron,
.cms-user__chevron {
    flex: none;
    inline-size: 1rem;
    block-size: 1rem;
    color: var(--haya-text-muted);
    transition: rotate 160ms ease;
}

/* The chevron turns while the list is open, as the shell's menu triggers do. */
.cms-tenant__pill:has(+ .cms-pop:popover-open) .cms-tenant__chevron {
    rotate: 180deg;
    color: var(--haya-brand);
}

.cms-tenant__warn {
    color: var(--haya-warning);
}

/* ---- popovers shared by the switcher, the user card and the theme menu.
   The shell's row-actions menu gives them the surface, the anchor and the
   top layer; this only sets the width and the extras. */

.cms-pop {
    min-inline-size: 16.5rem;
    max-inline-size: min(22rem, calc(100vw - 2rem));
    padding: 0.375rem;
}

/* Under the pill, start edges aligned, growing along the reading direction
   — the opposite of the table menu, which grows back into its table. */
.cms-tenant__menu {
    position-area: block-end span-inline-end;
    position-try-fallbacks:
        block-start span-inline-end,
        block-end span-inline-start,
        block-start span-inline-start;
}

/* Above the card, because the card is at the foot of the column. */
.cms-user__menu {
    position-area: block-start span-inline-end;
    position-try-fallbacks:
        block-end span-inline-end,
        block-start span-inline-start,
        block-end span-inline-start;
}

.cms-pop__heading {
    padding: 0.375rem 0.625rem 0.125rem;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--haya-text-muted);
}

.cms-pop__rule {
    border: 0;
    border-block-start: 1px solid var(--haya-border);
    margin: 0.25rem 0.25rem;
}

.cms-pop__search {
    margin-block-end: 0.25rem;
}

.cms-pop__empty {
    margin: 0.5rem 0.625rem;
    font-size: 0.8125rem;
    color: var(--haya-text-muted);
}

/* The list is a small thing: narrower than the pill's menu family, tighter
   rows, and the monogram and the name a size down from the pill's, centred on
   each other. */
.cms-tenant__menu {
    min-inline-size: 12.5rem;
    max-inline-size: 15rem;
    padding: 0.25rem;
    /* A capped column: the search box keeps its height, the list takes
       what is left and scrolls inside it. The viewport term keeps the menu
       on screen when the window is short. */
    max-block-size: min(22rem, calc(100dvh - 6rem));
    overflow: hidden;
}

.cms-tenant__menu > .cms-pop__search {
    flex: none;
}

.cms-tenant__list {
    flex: 1 1 auto;
    min-block-size: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
}

.cms-tenant__menu .cms-pop__heading {
    padding: 0.3rem 0.5rem 0.1rem;
    font-size: 0.625rem;
}

/* An option of the list: the row-actions item with the pill's own anatomy. */
.cms-tenant__option {
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.5rem;
    white-space: normal;
}

.cms-tenant__option .cms-tenant__mono {
    inline-size: 1.25rem;
    block-size: 1.25rem;
    border-radius: 0.3rem;
    font-size: 0.625rem;
}

/* Monogram and name, one line, centred on each other: no key under the name. */
.cms-tenant__option .cms-tenant__name {
    flex: 1;
    min-inline-size: 0;
    font-size: 0.75rem;
    font-weight: 500;
    line-height: 1.25rem;
}

.cms-theme__check {
    flex: none;
    margin-inline-start: auto;
    inline-size: 1rem;
    block-size: 1rem;
    color: var(--haya-brand);
}

/* ---- the user card at the foot */

.cms-user {
    flex: none;
    padding: 0.625rem;
    border-block-start: 1px solid var(--haya-border);
}

.cms-user__card {
    anchor-name: var(--haya-row-actions-anchor);
    inline-size: 100%;
    min-inline-size: 0;
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.5rem 0.5625rem;
    border: 1px solid transparent;
    border-radius: var(--haya-radius);
    background: transparent;
    color: var(--haya-text);
    font: inherit;
    text-align: start;
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease;
}

.cms-user__card:hover,
.cms-user__card:has(+ .cms-pop:popover-open) {
    background: var(--haya-surface-muted);
    border-color: var(--haya-border);
}

.cms-user__head {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.5rem 0.625rem 0.625rem;
}

.cms-user__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.375rem 0.625rem;
}

.cms-user__row-label {
    font-size: 0.8125rem;
}

/* Light, dark, system as one segmented control: the one in force is lifted
   onto the surface, the others sit in the groove. */
.cms-scheme-seg {
    display: inline-flex;
    gap: 2px;
    padding: 2px;
    border: 1px solid var(--haya-border);
    border-radius: calc(var(--haya-radius) + 2px);
    background: var(--haya-surface-muted);
}

.cms-scheme-seg__btn {
    display: grid;
    place-items: center;
    inline-size: 2rem;
    block-size: 1.75rem;
    padding: 0;
    border: 0;
    border-radius: var(--haya-radius);
    background: transparent;
    color: var(--haya-text-muted);
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
}

.cms-scheme-seg__btn:hover {
    color: var(--haya-text);
}

.cms-scheme-seg__btn--on {
    background: var(--haya-surface);
    color: var(--haya-brand);
    box-shadow: 0 1px 2px color-mix(in srgb, var(--haya-text) 12%, transparent);
}

.cms-scheme-seg__btn .cms-lucide {
    inline-size: 1rem;
    block-size: 1rem;
}

.cms-user__owner {
    align-items: flex-start;
    white-space: normal;
    text-decoration: none;
}

.cms-user__owner .cms-lucide {
    margin-block-start: 0.125rem;
    color: var(--haya-brand);
}

.cms-user__owner-text {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-inline-size: 0;
}

.cms-user__owner-text .cms-user__caption {
    white-space: normal;
}

.cms-user__menu form {
    display: contents;
}

/* ---- the appearance menu in the top bar */

.cms-theme__menu {
    min-inline-size: 12rem;
}

.cms-theme__option[aria-checked="true"] {
    background: color-mix(in srgb, var(--haya-brand) 10%, transparent);
}

.cms-theme__label {
    flex: 1;
}

.cms-theme__trigger .cms-lucide {
    inline-size: 1.125rem;
    block-size: 1.125rem;
    color: var(--haya-text-muted);
}

/* ---- the groups, reread as labels

   With the map's groups the whole column fits a laptop screen, so a header is
   a label over its rows more than a door in front of them: smaller, quieter,
   open by default. The fold stays for the operator's longer column. */
.cms-nav__summary {
    padding: 0.625rem 0.5625rem 0.25rem;
    font-size: 0.75rem;
}

.cms-nav__group--operator {
    margin-block-start: 0.5rem;
    padding-block-start: 0.5rem;
    border-block-start: 1px solid var(--haya-border);
}

/* The hub's row: one door, drawn as a plain row like the dashboard's. */
.cms-nav__hub {
    margin-block-start: 0.5rem;
}

.cms-settings__arrow {
    flex: none;
    margin-inline-start: auto;
    inline-size: 0.875rem;
    block-size: 0.875rem;
    color: var(--haya-text-muted);
}

/* The arrow points forward in the reading direction: the glyph is drawn for
   RTL and mirrored for LTR. */
[dir="ltr"] .cms-settings__arrow {
    scale: -1 1;
}

/* ---- the settings hub */

.cms-settings {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.cms-settings__search {
    max-inline-size: 28rem;
}

.cms-settings__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
    gap: 1rem;
}

.cms-settings__card {
    min-inline-size: 0;
    padding: 0.875rem 1rem 0.75rem;
    border-radius: var(--haya-radius-lg);
    background: var(--haya-surface);
    box-shadow: var(--cms-card-shadow);
}

.cms-settings__card-title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0 0 0.5rem;
    font-size: 0.875rem;
    font-weight: 700;
    color: var(--haya-text-muted);
}

.cms-settings__card-title .cms-lucide {
    inline-size: 1rem;
    block-size: 1rem;
}

.cms-settings__links {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.cms-settings__link {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.5rem 0.5rem;
    border-radius: var(--haya-radius);
    color: var(--haya-text);
    font-size: 0.875rem;
    text-decoration: none;
    transition: background-color 120ms ease;
}

.cms-settings__link:hover {
    background: var(--haya-surface-muted);
}

.cms-settings__link .cms-lucide,
.cms-settings__link .cms-nav__no-icon {
    inline-size: 1rem;
    block-size: 1rem;
}

.cms-settings__heading {
    margin: 0.75rem 0 0;
    font-size: 1rem;
}

.cms-settings__hint {
    margin: 0;
    font-size: 0.875rem;
    color: var(--haya-text-muted);
}

/* ---- the appearance reveal (cms-shell.js)

   While a scheme change runs inside a view transition, the new frame shows
   through the WebOne mark, in two states on one timeline, always from the
   centre of the screen:

     1. the mark scales up to a splash size and holds there, the new scheme
        inside it and the old one around it;
     2. it keeps growing until the solid area at the top of the W contains
        the whole page, which is where the reveal ends — inside the logo, not
        behind a fill.

   The mask is therefore anchored on that solid area (about 58.5% across and
   57% down the 78x50 artwork), not on the artwork's centre: the point that
   stays under the middle of the screen is the one that has to be opaque when
   the mark is huge. The size is a registered custom property so it can be
   animated; cms-shell.js sets the splash and final sizes from the viewport.
   The default cross-fade is switched off so only the reveal shows. */
@property --cms-reveal-s {
    syntax: '<length>';
    inherits: true;
    initial-value: 0px;
}

:root.cms-scheme-reveal::view-transition-old(root),
:root.cms-scheme-reveal::view-transition-new(root) {
    animation: none;
    mix-blend-mode: normal;
}

:root.cms-scheme-reveal::view-transition-new(root) {
    /* 78x50: the mark's height follows its width. */
    --cms-reveal-h: calc(var(--cms-reveal-s) * 50 / 78);
    animation: cms-scheme-reveal 1500ms linear forwards;
    /* Inline, so the first reveal of a page has nothing to fetch or decode
       that the warm-up has not already drawn (the same artwork as
       img/brand-mark-mask.svg). */
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%2278%22%20height=%2250%22%20viewBox=%220%200%2078%2050%22%3E%20%3Cpath%20fill=%22%23000%22%20d=%22M27.848%2033.949c.944%201.469%203.1%201.444%204.01-.046l6.354-10.398.064-.103c2.725-4.313%208.77-4.954%2012.337-1.308l.085.088L76.83%2049.69H62.282L47.545%2034.177a2.367%202.367%200%200%200-3.735.396l-7.114%2011.641c-3.02%204.942-10.136%205.061-13.33.267l-.075-.114L0%2010.137h12.54zm49.62%2012.743L66.92%2035.597v-25.35l-6.429%203.55V9.326L77.468%200z%22/%3E%20%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%2278%22%20height=%2250%22%20viewBox=%220%200%2078%2050%22%3E%20%3Cpath%20fill=%22%23000%22%20d=%22M27.848%2033.949c.944%201.469%203.1%201.444%204.01-.046l6.354-10.398.064-.103c2.725-4.313%208.77-4.954%2012.337-1.308l.085.088L76.83%2049.69H62.282L47.545%2034.177a2.367%202.367%200%200%200-3.735.396l-7.114%2011.641c-3.02%204.942-10.136%205.061-13.33.267l-.075-.114L0%2010.137h12.54zm49.62%2012.743L66.92%2035.597v-25.35l-6.429%203.55V9.326L77.468%200z%22/%3E%20%3C/svg%3E");
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: var(--cms-reveal-s) var(--cms-reveal-h);
    mask-size: var(--cms-reveal-s) var(--cms-reveal-h);
    -webkit-mask-position:
        calc(var(--cms-reveal-x, 50vw) - var(--cms-reveal-s) * 0.585)
        calc(var(--cms-reveal-y, 50vh) - var(--cms-reveal-h) * 0.57);
    mask-position:
        calc(var(--cms-reveal-x, 50vw) - var(--cms-reveal-s) * 0.585)
        calc(var(--cms-reveal-y, 50vh) - var(--cms-reveal-h) * 0.57);
}

/* The timeline, 1.5 s: a quick ease-out to the splash with a small
   overshoot that settles (0–450 ms), a hold (450–870 ms), then an
   accelerating expansion through to containment (870–1500 ms). Each keyframe
   names the easing of the segment that follows it. */
@keyframes cms-scheme-reveal {
    0% {
        --cms-reveal-s: 0px;
        animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1);
    }

    24% {
        --cms-reveal-s: calc(var(--cms-reveal-hero, 36vmin) * 1.06);
        animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1);
    }

    30% {
        --cms-reveal-s: var(--cms-reveal-hero, 36vmin);
        animation-timing-function: linear;
    }

    58% {
        --cms-reveal-s: var(--cms-reveal-hero, 36vmin);
        animation-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
    }

    100% {
        --cms-reveal-s: var(--cms-reveal-r, 900vmax);
    }
}

@media (prefers-reduced-motion: reduce) {
    :root.cms-scheme-reveal::view-transition-new(root) {
        animation: none;
        -webkit-mask-image: none;
        mask-image: none;
    }
}

/* The site's own addresses on its dashboard (CMS-L78): one row per name, the
   host read left to right in either panel language, the stage as a small
   coloured word and the certificate's end beside it. */
.cms-site-domains {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 0.5rem;
}

.cms-site-domains__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0.5rem;
    min-width: 0;
}

.cms-site-domains__host {
    font-weight: 600;
    unicode-bidi: isolate;
    overflow-wrap: anywhere;
    min-width: 0;
}

.cms-site-domains__stage {
    font-size: 0.8125rem;
    font-weight: 500;
}

.cms-site-domains__stage--ok { color: var(--haya-success); }
.cms-site-domains__stage--wait { color: var(--haya-warning); }
.cms-site-domains__stage--bad { color: var(--haya-danger); }

.cms-site-domains__until,
.cms-site-domains__note {
    color: var(--haya-text-muted);
    font-size: 0.8125rem;
}

.cms-site-domains__note {
    margin: 0.75rem 0 0;
}

.cms-site-domains__manage {
    display: inline-block;
    margin-top: 0.75rem;
    color: var(--haya-brand);
    font-weight: 500;
    text-decoration: none;
}

.cms-site-domains__manage:hover,
.cms-site-domains__manage:focus-visible {
    text-decoration: underline;
}
