/*
 * Ariana panel skin
 * ---------------------------------------------------------------------------
 * Loaded straight from public/ via a render hook, so it needs no Vite/npm build
 * on the customer's server. Everything here is presentation only.
 */

/* ---------------------------------------------------------------------------
 * Plus Jakarta Sans, self-hosted.
 *
 * NOT loaded from Google Fonts. Two reasons, both of which matter for who
 * Ariana is for: a request to fonts.googleapis.com on every admin page view
 * sends the operator's IP to a third party, which is a GDPR problem German
 * courts have already ruled on; and on a shared host in Iran or behind a
 * corporate proxy that request is often the slowest thing on the page, or
 * simply fails, leaving the panel in fallback type.
 *
 * Five static weights (400-800), one file each, ~12 KB apiece. The whole set is
 * the same size as the single variable file it replaces, but a page only fetches
 * the weights it actually uses - most screens need three, so they load roughly
 * 36 KB instead of 60. font-display: swap so the panel is readable before the
 * font arrives.
 *
 * Licensed under the SIL Open Font License 1.1; the full text ships beside the
 * file at ariana-assets/fonts/OFL.txt, which the licence requires.
 * ------------------------------------------------------------------------- */
@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('fonts/plus-jakarta-sans-v12-latin-regular.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('fonts/plus-jakarta-sans-v12-latin-500.woff2') format('woff2');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('fonts/plus-jakarta-sans-v12-latin-600.woff2') format('woff2');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('fonts/plus-jakarta-sans-v12-latin-700.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('fonts/plus-jakarta-sans-v12-latin-800.woff2') format('woff2');
    font-weight: 800;
    font-style: normal;
    font-display: swap;
}

:root {
    /* ---- Ariana's palette ---------------------------------------------------
     * The deep indigo-violet the panel has had from the beginning. An external
     * design-system sheet was briefly treated as authoritative here and has been
     * removed at the owner's instruction; these are the product's own values.
     *
     * This block is the brand's fixed identity. Components must NOT reach into
     * it directly - they use the mode-aware --ar-* layer below, which is the only
     * layer that knows whether the panel is light or dark.
     * -------------------------------------------------------------------- */
    --ariana-purple-900: #14102b;   /* page behind the panel   */
    --ariana-purple-850: #191436;   /* cards, sidebar          */
    --ariana-purple-800: #1e1840;   /* raised                  */
    --ariana-purple-700: #2a2158;   /* selected                */
    --ariana-purple-600: #382c74;   /* strong border           */
    --ariana-purple-line: #332a5e;  /* hairline                */
    --ariana-accent:     #7c6cff;   /* the violet              */

    /* Status colours, chosen for contrast on both a violet panel and violet
     * paper rather than taken from a framework's defaults. */
    --ariana-success: #16A34A;
    --ariana-warning: #D97706;
    --ariana-danger:  #DC2626;
    --ariana-info:    #2563EB;

    /* Radii, so components stop inventing their own. */
    --ariana-r-sm: 4px;
    --ariana-r-md: 8px;
    --ariana-r-lg: 12px;
    --ariana-r-xl: 16px;
    --ariana-r-2xl: 24px;
    --ariana-r-full: 999px;
}

/* ---------------------------------------------------------------------------
 * Semantic tokens that FLIP WITH THE MODE.
 *
 * These were being used throughout the stylesheet - var(--ar-ink),
 * var(--ar-line), var(--ar-ink-dim) - and never defined. Where a fallback was
 * given the component silently rendered in dark-mode colours on a white panel;
 * where none was given the declaration was invalid and dropped entirely.
 *
 * The palette above (--ariana-*) is the brand's fixed values. This layer is the
 * one components must use, because it is the only one that knows which mode is
 * active. A component that reaches past it for a literal hex will be unreadable
 * in one of the two modes, which is exactly how the panel ended up with white
 * text on a white background.
 *
 * Ink pairs are chosen per mode rather than shared: a single mid-tone that
 * "works on both" fails contrast on both.
 * ------------------------------------------------------------------------- */
:root {
    /* ---- Light mode: "violet paper" -----------------------------------------
     * The same violet as the dark panel, lit from the front instead of the back.
     *
     * Surfaces are violet-tinted neutrals rather than grey or white, so the
     * product reads as the same product in either mode. Ink is a deep violet
     * black, not #000, so nothing in the interface is a colour that does not
     * belong to the family.
     *
     * Every pair below was measured, not chosen by eye. The worst combination in
     * the whole palette is 4.75:1 (muted ink on the accent wash) and everything
     * else clears WCAG AA with margin; ink and dim ink clear AAA on every
     * surface. The numbers are in the table at the end of this block.
     *
     * The accent had to become mode-specific. Ariana's #7c6cff reads at only
     * 3.86:1 on white - it fails as a light-mode fill and as link text - while a
     * violet dark enough for light mode (#6B57F0 and below) fails as text on the
     * dark panel. There is no single value that serves both, so each mode gets
     * the darkest violet that still looks like Ariana.
     * --------------------------------------------------------------------- */
    --ar-canvas:   #F5F3FC;   /* page behind the cards            */
    --ar-surface:  #FFFFFF;   /* cards, panels, table body        */
    --ar-sunken:   #F0EDF9;   /* inset: code, transcripts, thead  */
    --ar-chrome:   #EFEBFA;   /* sidebar                          */
    --ar-wash:     #E4DEFB;   /* selected / active                */

    --ar-line:         #E4E0F2;
    --ar-line-strong:  #CFC8E6;

    --ar-ink:      #1B1436;   /* 17.50:1 on surface  AAA */
    --ar-ink-dim:  #4C4470;   /*  8.87:1 on surface  AAA */
    --ar-ink-mute: #645C82;   /*  6.19:1 on surface  AA  */

    --ar-accent:      #5F49E8;  /* fills: white label reads 5.83:1  */
    --ar-accent-ink:  #5334D0;  /* text and links: 7.58:1 on white  */
    --ar-accent-deep: #4C2BC4;  /* pressed / active                 */

    --ar-success-ink: #116932;
    --ar-warning-ink: #8A5205;
    --ar-warning-bg:  #FBF0DC;
    --ar-danger-ink:  #B91C1C;

    --ar-ring: rgba(95, 73, 232, .28);
}

.dark {
    /* The panel Ariana has always had: deep indigo-violet surfaces. */
    --ar-canvas:   var(--ariana-purple-900);
    --ar-surface:  var(--ariana-purple-850);
    --ar-sunken:   rgba(0, 0, 0, .28);
    --ar-chrome:   var(--ariana-purple-850);
    --ar-wash:     rgba(124, 108, 255, .16);

    --ar-line:         var(--ariana-purple-line);
    --ar-line-strong:  var(--ariana-purple-600);

    --ar-ink:      #E6E2FA;   /* 13.91:1 on the panel  AAA */
    --ar-ink-dim:  #A49DCD;   /*  6.93:1               AA  */
    --ar-ink-mute: #8A83AE;

    --ar-accent:      var(--ariana-accent);
    --ar-accent-ink:  #A99CFF;
    --ar-accent-deep: #9384FF;

    --ar-success-ink: #4ADE80;
    --ar-warning-ink: #FBBF24;
    --ar-warning-bg:  rgba(245, 158, 11, .12);
    --ar-danger-ink:  #F87171;

    --ar-ring: rgba(124, 108, 255, .38);
}

/* Vazirmatn (OFL), served locally — no third-party font host is contacted.
   The unicode-range is the whole trick: the browser downloads and uses these
   faces ONLY for Arabic-script characters, so Persian gets real typography
   while Latin text keeps Plus Jakarta. That means Vazirmatn can sit first in
   the panel's own stack below instead of fighting it from another file —
   which is what went wrong the first time: `.fi-body textarea` here (0,1,1)
   outranked `.ariana-assistant__input` in assistant.css (0,1,0), so Persian
   typed into the chat composer kept falling back to a system face. */
@font-face {
    font-family: 'Vazirmatn';
    src: url('fonts/Vazirmatn-Regular.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200D, U+FDFC, U+FDFD;
}

@font-face {
    font-family: 'Vazirmatn';
    src: url('fonts/Vazirmatn-Medium.woff2') format('woff2');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200D, U+FDFC, U+FDFD;
}

@font-face {
    font-family: 'Vazirmatn';
    src: url('fonts/Vazirmatn-Bold.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200D, U+FDFC, U+FDFD;
}

/* The panel typeface. Filament sets its own font stack on the body, so this
   has to be specific enough to win without !important on every element.
   Vazirmatn leads the stack for the Arabic script only (see the ranges
   above); every Latin glyph falls straight through to Plus Jakarta. */
.fi-body,
.fi-body input,
.fi-body select,
.fi-body textarea,
.fi-body button {
    font-family: 'Vazirmatn', 'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system,
        'Segoe UI', Roboto, sans-serif;
    font-feature-settings: 'ss01' 1, 'ss03' 1;
}

/* RTL blocks also get a touch more line height — Arabic script needs it. */
[dir="rtl"] .fi-body,
.fi-body [dir="rtl"] {
    font-family: 'Vazirmatn', 'IRANSans', 'Segoe UI', Tahoma, sans-serif;
    line-height: 1.75;
}

/* ===========================================================================
   1. Chrome — replace the default grey with a deep purple that sits with the
      dark dashboard instead of fighting it.
   ======================================================================== */

.dark .fi-topbar > nav,
.dark .fi-topbar nav.fi-topbar-nav,
.dark .fi-topbar {
    background-color: var(--ariana-purple-850) !important;
    border-bottom: 1px solid var(--ariana-purple-line) !important;
    box-shadow: 0 1px 0 0 rgba(255, 255, 255, .02);
}

.dark .fi-sidebar,
.dark .fi-sidebar-header,
.dark .fi-sidebar-nav {
    background-color: var(--ariana-purple-900) !important;
    border-color: var(--ariana-purple-line) !important;
}

.dark body,
.dark .fi-body,
.dark .fi-main-ctn {
    background-color: #100d21 !important;
}

/* Active sidebar item reads as brand, not default indigo-on-grey. */
.dark .fi-sidebar-item-active > .fi-sidebar-item-button,
.dark .fi-sidebar-item-active .fi-sidebar-item-label {
    background-color: var(--ariana-purple-700) !important;
    color: #fff !important;
}

.dark .fi-sidebar-item-button:hover {
    background-color: var(--ariana-purple-800) !important;
}

/* Cards and sections pick up the same family. */
.dark .fi-section,
.dark .fi-wi-stats-overview-stat,
.dark .fi-ta-ctn,
.dark .fi-fo-field-wrp .fi-input-wrp {
    background-color: var(--ariana-purple-850) !important;
    border-color: var(--ariana-purple-line) !important;
}

.dark .fi-section-header,
.dark .fi-ta-header-ctn {
    border-color: var(--ariana-purple-line) !important;
}

/* ===========================================================================
   1b. Brand wordmark — "ARIANA" in the panel's own typeface, white on dark.
       Text only; Filament renders this view in place of a logo image.

       Set in Plus Jakarta Sans rather than a system serif: the wordmark now
       looks the same on macOS, Windows and Linux, needs no font licence, and
       adds no download because the panel already loads this family.
   ======================================================================== */

.ariana-brand__word {
    font-family: 'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system,
                 'Segoe UI', sans-serif;
    font-size: 1.3rem;
    font-weight: 800;
    /* Capitals need air between them to read as a wordmark rather than a
       shouted word; the size drops a little to compensate for the extra width
       so the topbar still fits the hamburger and the user menu. */
    letter-spacing: .16em;
    text-transform: uppercase;
    line-height: 1.75rem;
    white-space: nowrap;
    color: #0f1020;
}

.dark .ariana-brand__word {
    color: #ffffff;
}

/* The site name beside the wordmark: "ARIANA (We Case Study)". One step
   smaller and lighter than the wordmark, and without its wide tracking, so
   the eye reads the product first and the site as context. It is the panel's
   answer to "which of my sites am I in?" — the same question the browser tab
   title answers. */
.ariana-brand__site {
    margin-inline-start: .5rem;
    font-family: 'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system,
                 'Segoe UI', sans-serif;
    font-size: .95rem;
    font-weight: 500;
    letter-spacing: .01em;
    line-height: 1.75rem;
    white-space: nowrap;
    opacity: .72;
    color: inherit;
}

/* A long site name must never push the user menu off the topbar; below the
   sidebar breakpoint the wordmark alone identifies the panel. */
@media (max-width: 1023.98px) {
    .ariana-brand__site {
        display: none;
    }
}

.dark .ariana-brand__site {
    color: #ffffff;
}

:root:not(.dark) .ariana-brand__site {
    color: #0f1020;
}

/* The logo wrapper is height-constrained; let the text sit centred in it. */
.fi-logo {
    display: flex;
    align-items: center;
}

/* ===========================================================================
   1c. Tabs (the SEO / Advanced box in the post editor) — it kept the default
       slate panel while everything around it turned purple.
   ======================================================================== */

.dark .fi-tabs,
.dark .fi-fo-tabs,
.dark .fi-sc-tabs,
.dark .fi-tabs-content,
.dark .fi-sc-tabs-content {
    background-color: var(--ariana-purple-850) !important;
    border-color: var(--ariana-purple-line) !important;
}

.dark .fi-tabs-item {
    color: #b9b2e0 !important;
}

.dark .fi-tabs-item-active,
.dark .fi-tabs-item[aria-selected="true"] {
    background-color: var(--ariana-purple-700) !important;
    color: #ffffff !important;
}

/* Panels nested inside a section (SERP preview, SEO analysis) */
.dark .fi-fo-field-wrp .fi-sc-component,
.dark .fi-section .fi-section {
    background-color: transparent !important;
}

/* ===========================================================================
   1d. Dark-mode contrast pass
       Anything that assumes a light background would otherwise render dark
       text on our dark chrome. Readability matters on every screen, so these
       are stated explicitly rather than left to inherited defaults.
   ======================================================================== */

.dark .fi-section-header-heading,
.dark .fi-section-header-description,
.dark .fi-header-heading,
.dark .fi-header-subheading,
.dark .fi-breadcrumbs-item-label,
.dark .fi-fo-field-wrp-label,
.dark .fi-fo-field-wrp-hint,
.dark .fi-ta-header-heading,
.dark .fi-ta-text-item-label,
.dark .fi-ta-col-label,
.dark .fi-in-entry-label,
.dark .fi-wi-stats-overview-stat-label,
.dark .fi-wi-stats-overview-stat-value,
.dark .fi-modal-heading,
.dark .fi-dropdown-list-item-label {
    color: var(--ar-ink) !important;
}

.dark .fi-fo-field-wrp-helper-text,
.dark .fi-section-header-description,
.dark .fi-ta-empty-state-description,
.dark .fi-wi-stats-overview-stat-description {
    color: #a49dcd !important;
}

/* Inputs: force a readable value colour and placeholder. */
.dark .fi-input,
.dark .fi-fo-select select,
.dark .fi-fo-rich-editor .tiptap,
.dark .fi-fo-textarea textarea,
.dark textarea,
.dark input[type="text"],
.dark input[type="email"],
.dark input[type="url"],
.dark input[type="number"],
.dark input[type="password"],
.dark input[type="search"] {
    color: #f3f1fd !important;
    background-color: transparent !important;
}

.dark .fi-input::placeholder,
.dark textarea::placeholder,
.dark input::placeholder {
    color: #8b84b8 !important;
}

/* Select dropdowns render their own listbox — keep it dark, not white. */
.dark .fi-fo-select-option,
.dark .fi-dropdown-panel,
.dark .fi-modal-window {
    background-color: var(--ariana-purple-850) !important;
    color: var(--ar-ink) !important;
    border-color: var(--ariana-purple-line) !important;
}

/* Native option elements inherit the OS palette on some browsers. */
.dark select option {
    background-color: #1e1840;
    color: #f3f1fd;
}

/* Tables */
.dark .fi-ta-row:hover {
    background-color: rgba(124, 108, 255, .08) !important;
}

.dark .fi-ta-header-cell,
.dark .fi-ta-cell {
    color: #e6e2fa;
}

/* Badges and chips keep their semantic colour but need a readable label. */
.dark .fi-badge {
    color: #ffffff;
}

/* Prose blocks (help text, editor content) */
.dark .fi-prose,
.dark .prose,
.dark .fi-fo-rich-editor-content {
    color: #e9e6fb !important;
}

.dark .fi-prose :is(h1, h2, h3, h4, strong),
.dark .prose :is(h1, h2, h3, h4, strong) {
    color: #ffffff !important;
}

/* ===========================================================================
   2. Global search — matched to the "View site" pill that sits beside it:
      same 2.25rem height, same full radius, same line/ink/accent tokens, so
      the topbar reads as one row of controls instead of two unrelated
      widgets. If .ariana-viewsite (§10) changes shape, change this with it —
      panel_ui_suite asserts the two agree on height and radius.
   ======================================================================== */

.fi-global-search-field .fi-input-wrp {
    height: 2.25rem;
    align-items: center;
    background-color: transparent !important;
    border: 1px solid var(--ar-line) !important;
    border-radius: var(--ariana-r-full, 999px);
    box-shadow: none !important;
    transition: color .15s ease, border-color .15s ease, background-color .15s ease;
}

.fi-global-search-field .fi-input-wrp:hover {
    border-color: var(--ar-accent) !important;
    background-color: var(--ar-wash) !important;
}

.fi-global-search-field .fi-input-wrp:focus-within {
    border-color: var(--ar-accent) !important;
    background-color: transparent !important;
    box-shadow: 0 0 0 3px var(--ar-ring) !important;
}

/* The input INSIDE the pill must be chrome-free: ariana-theme.css gives every
   .dark .fi-input its own surface-2 box and an indigo focus glow — right for
   form fields, wrong here, where it rendered as a second, smaller lit box
   inside the transparent pill the moment the field was focused (1.61.1). The
   pill's wrapper carries all of the border, background and focus treatment;
   the input carries none, in either mode, in every state. */
.fi-global-search-field .fi-input-wrp input,
.dark .fi-global-search-field .fi-input-wrp input,
.fi-global-search-field .fi-input-wrp input:focus,
.dark .fi-global-search-field .fi-input-wrp input:focus {
    height: 100%;
    padding-block: 0;
    font-size: .8rem;
    color: var(--ar-ink);
    background-color: transparent !important;
    border: 0 !important;
    border-radius: inherit;
    box-shadow: none !important;
    outline: none !important;
}

.fi-global-search-field .fi-input-wrp input::placeholder {
    color: var(--ar-ink-dim) !important;
}

/* The magnifier tracks the pill's ink exactly like the View site icon. */
.fi-global-search-field .fi-input-wrp svg {
    color: var(--ar-ink-dim);
}

/* A hard 18rem floor is wider than the free space in a phone topbar, which
   pushed the whole bar sideways and took the layout with it. The floor now
   only applies once there is room for it. */
.fi-global-search-field {
    min-width: 0;
    width: 100%;
}

@media (min-width: 768px) {
    .fi-global-search-field {
        min-width: 18rem;
        width: auto;
    }
}

/* ===========================================================================
   3. Rich editor — the toolbar overflowed its column and collided with the
      sidebar. Let it wrap and give the writing area real breathing room.
   ======================================================================== */

.fi-fo-rich-editor .fi-fo-rich-editor-toolbar,
.fi-fo-rich-editor-toolbar {
    display: flex !important;
    flex-wrap: wrap !important;
    gap: .25rem;
    row-gap: .35rem;
    overflow: visible !important;
}

.dark .fi-fo-rich-editor-toolbar {
    background-color: var(--ariana-purple-800) !important;
    border-color: var(--ariana-purple-line) !important;
}

/* Visual separation between button groups. */
.fi-fo-rich-editor-toolbar > div {
    display: flex;
    flex-wrap: wrap;
    gap: .15rem;
}

.fi-fo-rich-editor .fi-fo-rich-editor-content,
.fi-fo-rich-editor .tiptap {
    min-height: 26rem;
    line-height: 1.7;
}

/* The editor sat inside a rounded wrapper but kept square corners of its own,
   so the two never lined up. Round the whole stack and clip the children.

   `overflow: clip`, NOT `hidden`. They look identical, but `hidden` makes the
   element a scroll container, and a scroll container is the box a
   `position: sticky` descendant sticks INSIDE — which silently reduced the
   sticky toolbar below to an ordinary one that scrolled away with the article.
   `clip` clips the corners without creating a scroll container, so the toolbar
   sticks to the viewport as intended. A browser too old for `clip` drops the
   declaration and simply does not round the corners of the stack; the toolbar
   and the content already round their own, so nothing looks broken. */
.fi-fo-rich-editor,
.fi-fo-rich-editor .fi-input-wrp {
    border-radius: 12px !important;
    overflow: clip;
}

.fi-fo-rich-editor-toolbar {
    border-top-left-radius: 12px;
    border-top-right-radius: 12px;
}

/* ---- The toolbar follows the writer down a long article ------------------
 *
 * Formatting a heading two thousand words into a post meant scrolling back to
 * the top of the editor, applying the format, and scrolling back down. The
 * toolbar now stays put.
 *
 * `top: 4rem` is not a guess: Filament's own `.fi-topbar-ctn` is
 * `sticky top-0` with `min-h-16`, so 4rem is exactly where it stops. The
 * z-index sits BELOW the topbar's 30 so the two never fight, and above the
 * editor content so text scrolls under the toolbar rather than over it.
 *
 * The background has to be opaque. The toolbar's own background was
 * transparent — fine when it sat on the card, unreadable once article text
 * scrolls beneath it — so both modes get the panel's surface colour here.
 * ---------------------------------------------------------------------- */
/* DESCENDANT, not a child combinator. The toolbar is NOT a direct child of
   .fi-fo-rich-editor. Filament's real markup is:

       .fi-fo-rich-editor.fi-input-wrp
         └ .fi-input-wrp-content-ctn
             └ div[wire:ignore]              <- the editor's Alpine root
                 ├ .fi-fo-rich-editor-toolbar
                 └ .fi-fo-rich-editor-main

   Written as `>` this rule matched NOTHING and the toolbar never stuck. The
   selector is now asserted against the real rendered DOM by
   tests/harness/editor_toolbar_suite.mjs, not against this file's text. */
.fi-fo-rich-editor .fi-fo-rich-editor-toolbar {
    position: sticky;
    top: 4rem;
    z-index: 20;
    background-color: var(--ar-surface);
    /* The 1px border alone leaves a hairline of article text visible between
       the toolbar and what is scrolling under it on fractional zoom levels. */
    box-shadow: 0 1px 0 0 var(--ar-line);
}

.dark .fi-fo-rich-editor .fi-fo-rich-editor-toolbar {
    background-color: var(--ariana-purple-800);
}

/* The dropdown menus the toolbar opens must paint above the article text that
   is now scrolling beneath the sticky bar. */
.fi-fo-rich-editor .fi-fo-rich-editor-toolbar .fi-dropdown-panel,
.fi-fo-rich-editor .fi-fo-rich-editor-dropdown-tool-menu {
    z-index: 31;
}

/* Inside a modal the scroll container is the modal window, not the page, so
   there is no topbar to clear and a 4rem offset would push the toolbar into
   the middle of the dialog. Modals keep the ordinary toolbar. */
.fi-modal-window .fi-fo-rich-editor .fi-fo-rich-editor-toolbar {
    position: static;
    box-shadow: none;
}

/* A short viewport has no room to give up: a sticky toolbar plus the topbar
   would leave a few lines of writing area. */
@media (max-height: 520px) {
    .fi-fo-rich-editor .fi-fo-rich-editor-toolbar {
        position: static;
        box-shadow: none;
    }
}

/* ---- Tables inside the editor -------------------------------------------
 *
 * Kept deliberately in step with App\Services\Front\ContentStyles::tables(),
 * which supplies the same borders, padding and header treatment on the public
 * site. The point of the pair is that a table looks the same in both places;
 * if one is changed the other has to be changed with it.
 * ---------------------------------------------------------------------- */
.fi-fo-rich-editor .tiptap table {
    width: 100%;
    border-collapse: collapse;
    margin-block: 1rem;
    table-layout: fixed;
}

.fi-fo-rich-editor .tiptap :is(th, td) {
    border: 1px solid var(--ar-line-strong);
    padding: .5rem .65rem;
    text-align: start;
    vertical-align: top;
    position: relative;
}

.fi-fo-rich-editor .tiptap th {
    background: var(--ar-sunken);
    font-weight: 600;
}

.fi-fo-rich-editor .tiptap .selectedCell::after {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--ar-wash);
    pointer-events: none;
}

/* The column-resize handle tiptap draws between cells. */
.fi-fo-rich-editor .tiptap .column-resize-handle {
    position: absolute;
    inset-block: 0;
    inset-inline-end: -2px;
    width: 4px;
    background: var(--ar-accent);
    pointer-events: none;
}

.fi-fo-rich-editor .fi-fo-rich-editor-content,
.fi-fo-rich-editor .tiptap {
    border-bottom-left-radius: 12px;
    border-bottom-right-radius: 12px;
}

.fi-fo-rich-editor .tiptap:focus-visible,
.fi-fo-rich-editor .tiptap:focus {
    outline: none;
}

/* ===========================================================================
   4. Form layout — stop long values (author names, toggle labels) from
      shredding the narrow sidebar column.
   ======================================================================== */

.fi-fo-field-wrp .fi-fo-select .fi-input-wrp,
.fi-fo-field-wrp .choices__inner {
    min-width: 0;
}

.fi-fo-toggle-wrp,
.fi-fo-field-wrp label {
    word-break: normal;
    overflow-wrap: anywhere;
}

/* Upload diagnostics panel */
.ariana-diag {
    border: 1px solid var(--ariana-purple-line);
    border-radius: 12px;
    background: var(--ariana-purple-850);
    margin-bottom: 1.25rem;
}

.ariana-diag summary {
    cursor: pointer;
    padding: .8rem 1rem;
    font-weight: 600;
    font-size: .9rem;
    list-style: none;
    display: flex;
    align-items: center;
    gap: .6rem;
    color: var(--ar-ink);
}

.ariana-diag summary::-webkit-details-marker { display: none; }
.ariana-diag__ok  { color: var(--ar-success-ink); }
.ariana-diag__bad { color: var(--ar-danger-ink); }
.ariana-diag__chev { margin-left: auto; opacity: .55; font-weight: 500; font-size: .8rem; }

.ariana-diag__body { padding: 0 1rem 1rem; display: grid; gap: .45rem; }

.ariana-diag__row {
    display: grid;
    grid-template-columns: 1.2rem minmax(9rem, auto) auto 1fr;
    gap: .6rem;
    align-items: baseline;
    font-size: .8rem;
}

.ariana-diag__badge { font-weight: 800; }
.ariana-diag__badge.is-ok  { color: var(--ar-success-ink); }
.ariana-diag__badge.is-bad { color: var(--ar-danger-ink); }
.ariana-diag__label { color: var(--ar-ink-dim); }
.ariana-diag__value { color: var(--ar-ink); font-weight: 600; }
.ariana-diag__hint  { color: var(--ar-danger-ink); }

.ariana-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .6rem;
    margin-top: 1.1rem;
}

.ariana-upload-progress {
    display: flex;
    align-items: center;
    gap: .6rem;
    margin-top: 1rem;
    padding: .7rem .9rem;
    border-radius: 10px;
    border: 1px solid var(--ariana-purple-line);
    background: rgba(124, 108, 255, .08);
    font-size: .85rem;
    color: var(--ar-ink-dim);
}

/* ===========================================================================
   5. Server status widget
   ======================================================================== */

.ariana-server__summary {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: .75rem;
}

.ariana-server__item {
    background: rgba(255, 255, 255, .03);
    border: 1px solid var(--ariana-purple-line);
    border-radius: 10px;
    padding: .7rem .85rem;
    min-width: 0;
}

.ariana-server__label {
    display: block;
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    opacity: .6;
    margin-bottom: .2rem;
}

.ariana-server__value {
    display: block;
    font-size: .85rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ariana-server__toggle {
    margin-top: .9rem;
}

.ariana-server__chev--open svg {
    transform: rotate(180deg);
    transition: transform .2s ease;
}

.ariana-server__details {
    margin-top: 1rem;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 1rem;
}

.ariana-server__group {
    border: 1px solid var(--ariana-purple-line);
    border-radius: 10px;
    padding: .85rem 1rem;
    min-width: 0;
}

.ariana-server__group-title {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .07em;
    opacity: .65;
    margin: 0 0 .55rem;
}

.ariana-server__rows {
    display: grid;
    grid-template-columns: minmax(6rem, auto) 1fr;
    gap: .3rem .8rem;
    margin: 0;
    font-size: .78rem;
}

.ariana-server__rows dt {
    opacity: .6;
}

.ariana-server__rows dd {
    margin: 0;
    word-break: break-word;
}

[x-cloak] {
    display: none !important;
}

/* ===========================================================================
   6. About / update screen
   ======================================================================== */

.ariana-about__lead { color: var(--ar-ink-dim); line-height:1.7; margin:0 0 1.1rem; max-width:70ch; }

.ariana-about__facts {
    display:grid; grid-template-columns:repeat(auto-fit,minmax(11rem,1fr));
    gap:.7rem; margin:0;
}
.ariana-about__facts > div {
    border:1px solid var(--ariana-purple-line); border-radius:10px; padding:.65rem .8rem;
    background:rgba(255,255,255,.03);
}
.ariana-about__facts dt { font-size:.68rem; text-transform:uppercase; letter-spacing:.06em; opacity:.6; }
.ariana-about__facts dd { margin:.15rem 0 0; font-weight:600; font-size:.88rem; }

/* Update preview card */
.ariana-upd {
    border:1px solid var(--ariana-purple-line); border-radius:14px;
    background:linear-gradient(180deg, rgba(124,108,255,.10), transparent 60%), var(--ariana-purple-850);
    padding:1.4rem 1.5rem; margin-bottom:1.25rem;
}
.ariana-upd.is-blocked { background:var(--ariana-purple-850); border-color:#7f3a4a; }

.ariana-upd__head { display:flex; align-items:center; gap:.9rem; flex-wrap:wrap; margin-bottom:.9rem; }

.ariana-upd__badge {
    font-size:.66rem; font-weight:800; letter-spacing:.09em;
    /* mode-agnostic: white on a solid accent fill, correct in both modes */
    padding:.28rem .6rem; border-radius:6px; color:#fff;
}
.ariana-upd__badge--major { background:#dc2626; }
.ariana-upd__badge--minor { background: var(--ariana-accent); }
.ariana-upd__badge--patch { background:#0e9f6e; }

.ariana-upd__jump { font-size:1.05rem; color: var(--ar-ink-dim); display:flex; align-items:center; gap:.5rem; }
.ariana-upd__arrow { opacity:.5; }
.ariana-upd__to { color: var(--ar-ink); }

.ariana-upd__meta { display:flex; gap:1.1rem; flex-wrap:wrap; font-size:.78rem; color: var(--ar-ink-mute); margin-bottom:1.1rem; }
.ariana-upd__mig { color: var(--ar-warning-ink); }

.ariana-upd__title {
    font-size:.72rem; text-transform:uppercase; letter-spacing:.08em;
    opacity:.65; margin:0 0 .55rem;
}
/* Filament ships Tailwind's preflight, which resets every <ul> to
   list-style:none. A release-notes list without markers reads as a wall of
   sentences, so the marker is restored explicitly — and the indent is
   logical, so a Persian panel indents from the right. */
.ariana-upd__notes {
    margin: 0 0 1.2rem;
    padding-inline-start: 1.25rem;
    list-style: disc outside;
    color: var(--ar-ink);
    line-height: 1.75;
    font-size: .9rem;
}

.ariana-upd__notes li::marker { color: var(--ar-accent, #7c6cff); }
.ariana-upd__notes li { margin-bottom:.3rem; }

.ariana-upd__blocked { color: var(--ar-danger-ink); font-size:.9rem; line-height:1.6; margin:0 0 1.1rem; }

.ariana-upd__actions { display:flex; flex-wrap:wrap; gap:.6rem; }

.ariana-upd__safety {
    margin:1.2rem 0 0; padding-top:.9rem; border-top:1px solid var(--ariana-purple-line);
    color:#8b84b8; font-size:.76rem; line-height:1.6;
}
.ariana-upd__safety code {
    background:rgba(255,255,255,.06); padding:.05rem .35rem; border-radius:4px; font-size:.72rem;
}


/* ===========================================================================
   7. Tablet and phone
   ---------------------------------------------------------------------------
   The panel was built and checked at desktop width, and everything below is
   what that assumption cost on a smaller screen. Three failures account for
   almost all of it:

     1. A fixed `min-width` inside a flex row cannot shrink, so it pushes its
        parent wider than the viewport. One offender anywhere produces a
        horizontally scrolling page, and the sticky topbar then scrolls away
        from the content underneath it.
     2. A flex or grid ITEM defaults to `min-width: auto`, meaning it refuses
        to shrink below its content. A long author name, a category chip list
        or an unbroken URL therefore widens the whole row rather than wrapping.
        `min-width: 0` is the fix, and it has to be stated explicitly.
     3. Multi-column grids with no stacking breakpoint. At 360px a four-column
        row gives each column ~70px, which is narrower than the words in it.

   Breakpoints match Filament's own (640 / 768 / 1024 / 1280) so nothing here
   fights the framework's `sm:` / `md:` / `lg:` utilities. They stop .02px short
   of each one: `min-width: 640px` and `max-width: 640px` are BOTH true at
   exactly 640px, which makes that single viewport width render unlike either
   side of it. Ending at 639.98px removes the overlap without leaving a gap.
   ======================================================================== */

/* ---- 7.1 Overflow containment -------------------------------------------
   Applied at every width, not only on small screens: an element that cannot
   shrink is a latent bug on a desktop too, it just has more room to hide in. */

.fi-main,
.fi-main-ctn,
.fi-page,
.fi-section,
.fi-section-content,
.fi-fo-field-wrp,
.fi-ta-ctn {
    min-width: 0;
}

/* Cells hold user content of unknown length: a pasted URL with no spaces in it
   has no break opportunity at all unless one is granted. */
.fi-ta-cell,
.fi-ta-text-item-label,
.fi-in-entry-content,
.ariana-serp__url,
.ariana-serp__desc,
.ariana-server__rows dd {
    overflow-wrap: anywhere;
}

/* ---- 7.2 Tables ----------------------------------------------------------
   A data table cannot be made to fit a phone, so it scrolls - but it has to
   scroll INSIDE its own card rather than dragging the page with it. */

.fi-ta-ctn {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
}

@media (max-width: 1023.98px) {
    /* Tighter cells put roughly one more column on screen before scrolling. */
    .fi-ta-header-cell,
    .fi-ta-cell {
        padding-inline: .625rem;
    }

    /* The title column is the one a person is actually looking for; stop it
       collapsing to a two-word sliver while a badge column keeps its width. */
    .fi-ta-cell:first-child,
    .fi-ta-header-cell:first-child {
        padding-inline-start: .875rem;
    }
}

/* Secondary columns, marked on the resource rather than guessed at from
   position, so the header and the cell always disappear together and the
   table stays aligned. */
@media (max-width: 1279px) {
    .ariana-col-xl { display: none !important; }
}

@media (max-width: 1023px) {
    .ariana-col-lg { display: none !important; }
}

@media (max-width: 639px) {
    .ariana-col-md { display: none !important; }
}

/* The filter/search row above a table stacks instead of squeezing. */
@media (max-width: 639.98px) {
    .fi-ta-header-ctn .fi-ta-actions,
    .fi-ta-header-ctn > div {
        flex-wrap: wrap;
    }

    .fi-ta-search-field {
        width: 100%;
    }
}

/* ---- 7.3 Page chrome ----------------------------------------------------- */

@media (max-width: 1023.98px) {
    .fi-main {
        padding-inline: 1rem;
    }
}

@media (max-width: 639.98px) {
    .fi-main {
        padding-inline: .75rem;
        padding-block: 1rem;
    }

    .fi-header-heading {
        font-size: 1.3rem;
        line-height: 1.25;
    }

    /* Page-level action buttons sit under the heading rather than beside it,
       where they had about 90px to share. */
    .fi-header {
        flex-direction: column;
        align-items: stretch;
        gap: .75rem;
    }

    .fi-header-actions {
        flex-wrap: wrap;
    }

    .fi-section-content,
    .fi-section-header {
        padding: 1rem;
    }
}

@media (max-width: 480px) {
    /* Wide capitals with generous tracking crowd a 360px topbar, so both come
       down together rather than letting the wordmark wrap or clip. */
    .ariana-brand__word {
        font-size: 1.05rem;
        letter-spacing: .1em;
    }
}

/* ---- 7.4 Forms ----------------------------------------------------------- */

@media (max-width: 639.98px) {
    /* A button that is 40% of a phone's width is hard to hit and looks
       accidental. Full width is both easier and more deliberate. */
    .ariana-actions > .fi-btn,
    .ariana-actions > .fi-btn-ctn,
    .ariana-upd__actions > .fi-btn,
    .ariana-upd__actions > .fi-btn-ctn {
        width: 100%;
        justify-content: center;
    }

    .ariana-actions__note {
        order: 99;
    }

    /* Every interactive control clears the 44px touch target guideline. */
    .fi-btn,
    .fi-tabs-item,
    .fi-sidebar-item-button,
    .fi-dropdown-list-item {
        min-height: 2.75rem;
    }

    .fi-input,
    .fi-select-input,
    .fi-fo-textarea textarea {
        /* Anything under 16px makes iOS Safari zoom the page on focus, and it
           never zooms back out. */
        font-size: 16px;
    }
}

/* ---- Tab strips: fade and page, never scroll ------------------------------
   Settings carries eleven tabs and a laptop fits about seven. The browser's
   answer is a horizontal scrollbar: a grey bar under the tabs, a hard cut at
   the edge, and no sign that anything follows. Ariana's answer is the pattern
   every modern app uses — the overflowing edge fades out and a round chevron
   appears there to page the strip along.

   The buttons come from panel-tabs.js, which also sets the two data
   attributes below. The stylesheet alone still degrades correctly: with no
   JavaScript the strip simply scrolls, exactly as it did before. */
.fi-tabs {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scroll-behavior: smooth;

    /* The scrollbar is replaced by the fade, not merely hidden: the fade and
       the chevron together carry the same information more quietly. */
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.fi-tabs::-webkit-scrollbar {
    width: 0;
    height: 0;
}

.fi-tabs > * {
    flex-shrink: 0;
}

/* The host is whatever element wraps the strip — the schema tabs container,
   the list page's tab column, the sub-navigation bar. It only ever gains a
   positioning context, so no layout it already had can shift. */
.ariana-tabnav-host {
    position: relative;
}

/* display:contents so the injected wrapper contributes no box of its own:
   the two buttons position against the host, and a flex or grid host counts
   the same children it did before the script ran. */
.ariana-tabnav {
    display: contents;
}

.ariana-tabnav__btn {
    position: absolute;

    /* The host contains the tab panels as well as the strip, so the centre
       line comes from the script, which measures the strip itself. The 50%
       fallback only applies in the instant before the first measurement. */
    top: var(--ariana-tabnav-y, 50%);
    z-index: 5;
    display: none;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    padding: 0;
    border: 1px solid var(--ar-line, rgba(255, 255, 255, .12));
    border-radius: 999px;
    background: var(--ar-surface, #1b1636);
    color: inherit;
    opacity: .85;
    cursor: pointer;
    pointer-events: auto;
    transform: translateY(-50%);
    box-shadow: 0 2px 10px rgba(0, 0, 0, .35);
    transition: opacity .15s ease, background-color .15s ease, transform .15s ease;
}

.ariana-tabnav__btn:hover {
    opacity: 1;
    background: var(--ar-wash, rgba(124, 108, 255, .16));
}

.ariana-tabnav__btn:active {
    transform: translateY(-50%) scale(.94);
}

.ariana-tabnav__btn:focus-visible {
    outline: 2px solid var(--ar-accent, #7c6cff);
    outline-offset: 2px;
    opacity: 1;
}

.ariana-tabnav__btn svg {
    width: .85rem;
    height: .85rem;
}

/* Logical placement: "previous" sits at the start of the strip, which is the
   right-hand side in Persian and Arabic. inset-inline handles that with no
   RTL-specific rule. */
.ariana-tabnav__btn--prev {
    inset-inline-start: .125rem;
}

.ariana-tabnav__btn--next {
    inset-inline-end: .125rem;
}

/* The chevron is drawn pointing towards the start; the "next" one is the same
   glyph mirrored, and in RTL both mirror again. */
.ariana-tabnav__btn--next svg {
    transform: scaleX(-1);
}

[dir="rtl"] .ariana-tabnav__btn--prev svg {
    transform: scaleX(-1);
}

[dir="rtl"] .ariana-tabnav__btn--next svg {
    transform: none;
}

/* Only the side that actually has hidden tabs shows a button. */
.ariana-tabnav-host[data-ariana-tabs="start"] > .ariana-tabnav > .ariana-tabnav__btn--prev,
.ariana-tabnav-host[data-ariana-tabs="both"] > .ariana-tabnav > .ariana-tabnav__btn--prev,
.ariana-tabnav-host[data-ariana-tabs="end"] > .ariana-tabnav > .ariana-tabnav__btn--next,
.ariana-tabnav-host[data-ariana-tabs="both"] > .ariana-tabnav > .ariana-tabnav__btn--next {
    display: inline-flex;
}

/* The fade. data-ariana-fade is physical (left/right) because a mask gradient
   has no logical form; panel-tabs.js resolves the direction before setting
   it, so this stylesheet never has to guess. */
.ariana-tabnav-host[data-ariana-fade="right"] > .fi-tabs {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 3.5rem), transparent 100%);
    mask-image: linear-gradient(to right, #000 calc(100% - 3.5rem), transparent 100%);
}

.ariana-tabnav-host[data-ariana-fade="left"] > .fi-tabs {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 3.5rem);
    mask-image: linear-gradient(to right, transparent 0, #000 3.5rem);
}

.ariana-tabnav-host[data-ariana-fade="left right"] > .fi-tabs {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 3.5rem, #000 calc(100% - 3.5rem), transparent 100%);
    mask-image: linear-gradient(to right, transparent 0, #000 3.5rem, #000 calc(100% - 3.5rem), transparent 100%);
}

/* Room for the button so it never covers a label at the very edge. */
.ariana-tabnav-host[data-ariana-tabs="start"] > .fi-tabs,
.ariana-tabnav-host[data-ariana-tabs="both"] > .fi-tabs {
    scroll-padding-inline-start: 2.25rem;
}

.ariana-tabnav-host[data-ariana-tabs="end"] > .fi-tabs,
.ariana-tabnav-host[data-ariana-tabs="both"] > .fi-tabs {
    scroll-padding-inline-end: 2.25rem;
}

@media (max-width: 767.98px) {
    .fi-tabs-item {
        white-space: nowrap;
    }

    /* On a touch screen the finger is the affordance; the fade stays, the
       buttons would only cover tabs on a narrow strip. */
    .ariana-tabnav__btn {
        display: none !important;
    }
}

@media (prefers-reduced-motion: reduce) {
    .fi-tabs {
        scroll-behavior: auto;
    }

    .ariana-tabnav__btn {
        transition: none;
    }
}

/* The rich editor reserved 26rem of height, which is most of a phone screen
   before a single toolbar button is drawn. */
@media (max-width: 767.98px) {
    .fi-fo-rich-editor .fi-fo-rich-editor-content,
    .fi-fo-rich-editor .tiptap {
        min-height: 16rem;
    }

    .fi-fo-rich-editor-toolbar {
        padding: .35rem;
        gap: .2rem;
    }

    .fi-fo-rich-editor-toolbar .fi-icon-btn {
        padding: .35rem;
    }
}

/* ---- 7.5 Ariana components ---------------------------------------------- */

@media (max-width: 639.98px) {
    /* Four columns at 360px gave each label about 70px. */
    .ariana-diag__row {
        grid-template-columns: 1.2rem 1fr;
        row-gap: .15rem;
    }

    .ariana-diag__value,
    .ariana-diag__hint {
        grid-column: 2;
    }

    .ariana-diag summary {
        flex-wrap: wrap;
        row-gap: .25rem;
    }

    .ariana-diag__chev {
        margin-left: 0;
    }

    .ariana-upd {
        padding: 1rem;
        border-radius: 12px;
    }

    .ariana-upd__jump {
        font-size: .95rem;
    }

    .ariana-upd__meta {
        gap: .5rem 1rem;
    }

    .ariana-server__summary {
        grid-template-columns: 1fr 1fr;
    }

    .ariana-server__details {
        grid-template-columns: 1fr;
    }

    /* The SEO / Readability score pair, and the analysis panel generally. */
    .ariana-grid-2 {
        grid-template-columns: 1fr;
    }

    .ariana-serp {
        padding: .75rem;
    }

    .ariana-counts {
        flex-wrap: wrap;
        gap: .35rem 1rem;
    }

    .ariana-issues__item {
        flex-direction: column;
        align-items: flex-start;
        gap: .375rem;
    }

    /* A 12px link is not a comfortable target; give it room without changing
       how it looks. */
    .ariana-issues__link {
        display: inline-flex;
        align-items: center;
        min-height: 2.25rem;
    }

    .ariana-about__facts {
        grid-template-columns: 1fr 1fr;
    }
}

@media (max-width: 420px) {
    .ariana-server__summary,
    .ariana-about__facts {
        grid-template-columns: 1fr;
    }

    /* Label above value, so neither is truncated to initials. */
    .ariana-server__rows {
        grid-template-columns: 1fr;
        gap: .1rem;
    }

    .ariana-server__rows dt {
        margin-top: .4rem;
    }

    /* The nowrap + ellipsis that keeps these tidy on desktop hides most of a
       long value on a narrow one. */
    .ariana-server__value {
        white-space: normal;
        overflow-wrap: anywhere;
    }
}

/* ---- 7.6 Media library grid --------------------------------------------- */

@media (max-width: 1023.98px) {
    .ariana-media-grid {
        grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
    }
}

@media (max-width: 480px) {
    .ariana-media-grid {
        grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
        gap: .5rem;
    }
}

/* ---- 7.6b Visual media picker -------------------------------------------
 *
 * The field, and the dialog it teleports into <body>. Everything is written
 * with logical properties — inset-inline, margin-inline, text-align: start —
 * so the whole picker mirrors in Persian and Arabic without a second sheet.
 * ---------------------------------------------------------------------- */

/* THE FIELD MEASURES ITSELF, NOT THE WINDOW
   -----------------------------------------
   The picker sits in the post form's narrow side column, so a viewport media
   query says nothing useful about the space it actually has: on a laptop the
   window is wide while this column is ~300px. The field is therefore an
   inline-size container and its own rules respond to ITS width.

   What went wrong without that: the row was `nowrap`, the button carried
   `white-space: nowrap`, and the text column had `min-width: 0` with
   `overflow-wrap: anywhere` — so the text was the only part that could give,
   and "No featured image chosen" collapsed into a one-letter-per-line
   column. The text column now has a real floor (`min-inline-size`), and when
   the container cannot honour it the layout switches to stacked instead of
   crushing anything. */
.ariana-mediapicker {
    container-type: inline-size;
    container-name: ariana-picker;
}

.ariana-mediapicker__current {
    display: flex;
    align-items: center;
    flex-wrap: wrap;              /* fallback where container queries are absent */
    gap: .75rem;
    padding: .7rem;
    border: 1px solid var(--ar-line);
    border-radius: 12px;
    background: var(--ar-surface);
}

.ariana-mediapicker__thumb {
    flex: 0 0 auto;
    width: 76px;
    height: 76px;
    border-radius: 10px;
    border: 1px solid var(--ar-line);
    background: var(--ar-sunken);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--ar-ink-mute);
}

.ariana-mediapicker__thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.ariana-mediapicker__summary {
    /* A floor, not zero: below this the row restacks (see the container
       query) rather than squeezing the label letter by letter. */
    flex: 1 1 9rem;
    min-inline-size: 9rem;
}

.ariana-mediapicker__name {
    margin: 0;
    font-weight: 600;
    font-size: .875rem;
    color: var(--ar-ink);
    overflow-wrap: anywhere;
}

.ariana-mediapicker__meta {
    margin: .2rem 0 0;
    font-size: .74rem;
    color: var(--ar-ink-mute);
    overflow-wrap: anywhere;
}

.ariana-mediapicker__warn {
    margin: .25rem 0 0;
    font-size: .74rem;
    color: var(--ar-warning-ink);
}

.ariana-mediapicker__buttons {
    display: flex;
    flex-direction: column;
    gap: .35rem;
    flex: 0 0 auto;
}

/* Narrow column: thumbnail and text keep their row, the buttons take a full
   line of their own and split it evenly — same height, same radius, same gap
   as everywhere else, and it mirrors in RTL because nothing here is
   left/right. */
@container ariana-picker (max-width: 26rem) {
    .ariana-mediapicker__current {
        display: grid;
        grid-template-columns: auto 1fr;
        align-items: center;
        column-gap: .75rem;
        row-gap: .6rem;
    }

    .ariana-mediapicker__summary {
        flex: initial;
        min-inline-size: 0;       /* the grid track already guarantees room */
    }

    .ariana-mediapicker__buttons {
        grid-column: 1 / -1;
        flex-direction: row;
    }

    .ariana-mediapicker__buttons .ariana-mediapicker__btn {
        flex: 1 1 0;
        white-space: normal;      /* it has the width now; no need to overflow */
    }
}

/* Very narrow (a phone, or a collapsed column): the thumbnail leads its own
   row so the label always has the full width. */
@container ariana-picker (max-width: 17rem) {
    .ariana-mediapicker__current {
        grid-template-columns: 1fr;
        justify-items: start;
    }

    .ariana-mediapicker__buttons { grid-column: auto; inline-size: 100%; }
}

.ariana-mediapicker__btn {
    appearance: none;
    border: 1px solid transparent;
    border-radius: 9px;
    padding: .4rem .75rem;
    font-size: .78rem;
    font-weight: 600;
    cursor: pointer;
    background: var(--ar-accent);
    color: #fff;
    white-space: nowrap;
}

.ariana-mediapicker__btn:disabled {
    opacity: .5;
    cursor: not-allowed;
}

.ariana-mediapicker__btn--quiet {
    background: transparent;
    color: var(--ar-ink-dim);
    border-color: var(--ar-line-strong);
}

/* ---- the dialog ---- */

.ariana-mediapicker__overlay {
    position: fixed;
    inset: 0;
    /* Above Filament's own modals (z-40) so the picker opened from inside the
       editor's insert-image dialog is not painted underneath it. */
    z-index: 60;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.25rem;
}

.ariana-mediapicker__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(10, 8, 24, .62);
}

.ariana-mediapicker__dialog {
    position: relative;
    display: flex;
    flex-direction: column;
    width: min(1040px, 100%);
    max-height: min(760px, 92dvh);
    border-radius: 16px;
    background: var(--ar-surface);
    border: 1px solid var(--ar-line);
    box-shadow: 0 24px 60px rgba(0, 0, 0, .35);
    overflow: hidden;
}

.ariana-mediapicker__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .85rem 1rem;
    border-bottom: 1px solid var(--ar-line);
}

.ariana-mediapicker__head h2 {
    margin: 0;
    font-size: .95rem;
    font-weight: 700;
    color: var(--ar-ink);
}

.ariana-mediapicker__close {
    appearance: none;
    border: 0;
    background: transparent;
    color: var(--ar-ink-dim);
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
    padding: .15rem .4rem;
}

.ariana-mediapicker__search {
    padding: .7rem 1rem;
    border-bottom: 1px solid var(--ar-line);
}

.ariana-mediapicker__search input {
    width: 100%;
    padding: .5rem .7rem;
    border-radius: 9px;
    border: 1px solid var(--ar-line-strong);
    background: var(--ar-sunken);
    color: var(--ar-ink);
    font-size: .85rem;
}

.ariana-mediapicker__body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: 0;
    min-height: 0;
    flex: 1 1 auto;
}

.ariana-mediapicker__grid-ctn {
    min-width: 0;
    overflow-y: auto;
    padding: 1rem;
}

.ariana-mediapicker__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(122px, 1fr));
    gap: .65rem;
}

.ariana-mediapicker__tile {
    position: relative;
    appearance: none;
    padding: 0;
    cursor: pointer;
    border: 2px solid transparent;
    border-radius: 10px;
    background: var(--ar-sunken);
    overflow: hidden;
    text-align: start;
}

.ariana-mediapicker__tile.is-active {
    border-color: var(--ar-accent);
}

.ariana-mediapicker__tile img {
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
}

.ariana-mediapicker__tile-name {
    display: block;
    padding: .3rem .4rem;
    font-size: .68rem;
    line-height: 1.3;
    color: var(--ar-ink-dim);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ariana-mediapicker__tile-flag {
    position: absolute;
    inset-block-start: .3rem;
    inset-inline-end: .3rem;
    width: 1.05rem;
    height: 1.05rem;
    border-radius: 50%;
    background: var(--ar-warning-ink);
    color: #fff;
    font-size: .68rem;
    font-weight: 700;
    line-height: 1.05rem;
    text-align: center;
}

.ariana-mediapicker__side {
    border-inline-start: 1px solid var(--ar-line);
    padding: 1rem;
    overflow-y: auto;
    background: var(--ar-canvas);
}

.ariana-mediapicker__preview {
    border-radius: 10px;
    border: 1px solid var(--ar-line);
    background: var(--ar-sunken);
    overflow: hidden;
    margin-block-end: .5rem;
}

.ariana-mediapicker__preview img {
    display: block;
    width: 100%;
    max-height: 190px;
    object-fit: contain;
}

.ariana-mediapicker__fields {
    display: flex;
    flex-direction: column;
    gap: .55rem;
    margin-block-start: .75rem;
}

.ariana-mediapicker__fields label {
    display: flex;
    flex-direction: column;
    gap: .2rem;
    font-size: .72rem;
    font-weight: 600;
    color: var(--ar-ink-dim);
}

.ariana-mediapicker__fields :is(input, textarea) {
    width: 100%;
    padding: .4rem .55rem;
    border-radius: 8px;
    border: 1px solid var(--ar-line-strong);
    background: var(--ar-surface);
    color: var(--ar-ink);
    font-size: .8rem;
    font-weight: 400;
    resize: vertical;
}

.ariana-mediapicker__note {
    margin: .6rem 0 0;
    font-size: .75rem;
    color: var(--ar-ink-mute);
}

.ariana-mediapicker__more {
    margin-block-start: .85rem;
}

.ariana-mediapicker__foot {
    display: flex;
    justify-content: flex-end;
    gap: .5rem;
    padding: .75rem 1rem;
    border-top: 1px solid var(--ar-line);
}

@media (max-width: 820px) {
    .ariana-mediapicker__body {
        grid-template-columns: minmax(0, 1fr);
    }

    .ariana-mediapicker__side {
        border-inline-start: 0;
        border-top: 1px solid var(--ar-line);
    }

    .ariana-mediapicker__current {
        flex-wrap: wrap;
    }

    .ariana-mediapicker__buttons {
        flex-direction: row;
        width: 100%;
    }
}

/* ---- 7.7 Modals ---------------------------------------------------------- */

@media (max-width: 639.98px) {
    /* A centred modal with desktop margins leaves a sliver of content; on a
       phone it should behave like a sheet. */
    .fi-modal-window {
        margin: 0;
        max-height: 100dvh;
        border-radius: 14px 14px 0 0;
    }

    .fi-modal-content {
        padding: 1rem;
    }

    .fi-modal-footer-actions {
        flex-direction: column-reverse;
        align-items: stretch;
        gap: .5rem;
    }

    .fi-modal-footer-actions .fi-btn {
        width: 100%;
        justify-content: center;
    }
}

/* ---- 7.8 Landscape phones ------------------------------------------------
   A short viewport turns generous vertical rhythm into scrolling. */

@media (max-height: 480px) and (orientation: landscape) {
    .fi-fo-rich-editor .fi-fo-rich-editor-content,
    .fi-fo-rich-editor .tiptap {
        min-height: 12rem;
    }

    .fi-main {
        padding-block: .75rem;
    }
}

/* ---- Generated theme prompt preview -------------------------------------- */

.ariana-prompt__text {
    width: 100%;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .78rem;
    line-height: 1.55;
    padding: .85rem;
    border-radius: 10px;
    border: 1px solid var(--ar-line);
    background: var(--ar-sunken);
    color: var(--ar-ink);
    resize: vertical;
    white-space: pre;
    overflow-wrap: normal;
    overflow-x: auto;
}

.ariana-prompt__hint {
    margin: .5rem 0 0;
    font-size: .75rem;
    color: var(--ar-ink-dim);
}

/* ===========================================================================
   9. Media file cards
      A file with no picture still has to be identifiable at a glance, and the
      thing people scan a library for is the format. So the extension is the
      icon rather than a caption under a generic document glyph.

      Tones are stated twice: the darker value carries the light panel, the
      lighter value the dark one. Setting a single mid-tone would have left the
      label under-contrasted on one of them.
   ======================================================================== */

.ariana-filecard {
    --file-size: 56px;
    --file-accent: #64748b;
    --file-tint: rgba(100, 116, 139, .12);

    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: var(--file-size);
    height: var(--file-size);
    border-radius: 10px;
    overflow: hidden;
    background: var(--file-tint);
    border: 1px solid color-mix(in srgb, var(--file-accent) 34%, transparent);
    color: var(--file-accent);
}

/* Images keep the same footprint and radius as the icon cards so rows do not
   jump in height when the library mixes pictures and documents. */
.ariana-filecard--image {
    object-fit: cover;
    background: var(--ar-sunken);
    border-color: var(--ariana-purple-line, rgba(51, 42, 94, .8));
    color: inherit;
}

.ariana-filecard__sheet {
    position: absolute;
    width: 62%;
    height: 62%;
    opacity: .3;
}

.ariana-filecard__ext {
    position: relative;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: calc(var(--file-size) * .21);
    font-weight: 700;
    letter-spacing: .04em;
    line-height: 1;
    text-transform: uppercase;
}

/* Light panel: 600-level tones, dark enough to read on a pale tint. */
.ariana-filecard--pdf   { --file-accent: #dc2626; --file-tint: rgba(220, 38, 38, .10); }
.ariana-filecard--doc   { --file-accent: #2563eb; --file-tint: rgba(37, 99, 235, .10); }
.ariana-filecard--sheet { --file-accent: #16a34a; --file-tint: rgba(22, 163, 74, .10); }
.ariana-filecard--slide { --file-accent: #ea580c; --file-tint: rgba(234, 88, 12, .10); }
.ariana-filecard--zip   { --file-accent: #ca8a04; --file-tint: rgba(202, 138, 4, .10); }
.ariana-filecard--code  { --file-accent: #0891b2; --file-tint: rgba(8, 145, 178, .10); }
.ariana-filecard--text  { --file-accent: #475569; --file-tint: rgba(71, 85, 105, .10); }
.ariana-filecard--media { --file-accent: #7c3aed; --file-tint: rgba(124, 58, 237, .10); }
/* Audio: teal, distinct from video's violet so the two are told apart at a
   glance in a mixed library, and away from the panel's own accent. */
.ariana-filecard--audio { --file-accent: #0d9488; --file-tint: rgba(13, 148, 136, .10); }
.ariana-filecard--font  { --file-accent: #db2777; --file-tint: rgba(219, 39, 119, .10); }

/* Dark panel: 400-level tones on a deeper tint. */
.dark .ariana-filecard--pdf   { --file-accent: #f87171; --file-tint: rgba(248, 113, 113, .13); }
.dark .ariana-filecard--doc   { --file-accent: #60a5fa; --file-tint: rgba(96, 165, 250, .13); }
.dark .ariana-filecard--sheet { --file-accent: #4ade80; --file-tint: rgba(74, 222, 128, .13); }
.dark .ariana-filecard--slide { --file-accent: #fb923c; --file-tint: rgba(251, 146, 60, .13); }
.dark .ariana-filecard--zip   { --file-accent: #fbbf24; --file-tint: rgba(251, 191, 36, .13); }
.dark .ariana-filecard--code  { --file-accent: #22d3ee; --file-tint: rgba(34, 211, 238, .13); }
.dark .ariana-filecard--text  { --file-accent: #cbd5e1; --file-tint: rgba(203, 213, 225, .11); }
.dark .ariana-filecard--media { --file-accent: #c084fc; --file-tint: rgba(192, 132, 252, .13); }
.dark .ariana-filecard--audio { --file-accent: #2dd4bf; --file-tint: rgba(45, 212, 191, .13); }
.dark .ariana-filecard--font  { --file-accent: #f472b6; --file-tint: rgba(244, 114, 182, .13); }
.dark .ariana-filecard--other { --file-accent: #94a3b8; --file-tint: rgba(148, 163, 184, .11); }

/* color-mix is recent. Where it is unsupported the border simply falls back to
   the panel line colour instead of disappearing. */
@supports not (border-color: color-mix(in srgb, red 30%, transparent)) {
    .ariana-filecard { border-color: var(--ariana-purple-line, rgba(51, 42, 94, .8)); }
}

/* The edit screen shows the same card at a larger size, next to the metadata. */
.ariana-filepreview {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.ariana-filepreview__meta {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    min-width: 0;
}

.ariana-filepreview__name {
    font-weight: 600;
    word-break: break-all;
}

.ariana-filepreview__sub {
    font-size: .8rem;
    color: var(--ar-ink-dim);
}

/* ===========================================================================
   10. "View site" topbar link
      Present on every screen so leaving the panel to look at the result is
      never a hunt through the menu. Quiet by default - it sits beside the
      search field and must not compete with it - and only picks up the brand
      colour on hover.
   ======================================================================== */

.ariana-viewsite {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    height: 2.25rem;
    padding: 0 .75rem;
    /* No margin. The link now sits inside .fi-topbar-end, which already applies
       a column-gap; adding a margin on top of it made this one control sit
       differently from everything else in the topbar. */
    border-radius: var(--ariana-r-full, 999px);
    border: 1px solid var(--ar-line);
    font-size: .8rem;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
    color: var(--ar-ink-dim);
    text-decoration: none;
    transition: color .15s ease, border-color .15s ease, background-color .15s ease;
}

.ariana-viewsite:hover,
.ariana-viewsite:focus-visible {
    color: var(--ar-ink);
    border-color: var(--ar-accent);
    background: var(--ar-wash);
}

.ariana-viewsite:focus-visible {
    outline: 2px solid var(--ar-accent);
    outline-offset: 2px;
}

.ariana-viewsite__icon {
    width: 1rem;
    height: 1rem;
    flex: 0 0 auto;
}

/* On a narrow screen the icon carries the meaning on its own; the topbar has
   no room for the word next to the search field. */
@media (max-width: 767px) {
    .ariana-viewsite__label { display: none; }
    .ariana-viewsite { padding: 0 .55rem; }
}

/* ===========================================================================
   11. Mail test log
      A failed mail configuration is the single most common support request a
      CMS receives, and the usual answer - "could not send email" - starts a
      guessing game. This box is sized to hold the real answer: what was tried,
      what the server said, and which likely cause it is.
   ======================================================================== */

.ariana-maillog {
    border: 1px solid var(--ar-line);
    border-radius: 12px;
    background: var(--ar-sunken);
    padding: 1rem;
    font-size: .82rem;
}

.ariana-maillog--ok  { border-color: rgba(34, 197, 94, .38); }
.ariana-maillog--bad { border-color: rgba(239, 68, 68, .38); }

.ariana-maillog--empty {
    display: flex;
    align-items: flex-start;
    gap: .65rem;
    color: var(--ar-ink-dim);
}

.ariana-maillog--empty p { margin: 0; line-height: 1.6; }

.ariana-maillog__emptyicon {
    width: 1.1rem;
    height: 1.1rem;
    flex: 0 0 auto;
    margin-top: .1rem;
    opacity: .7;
}

.ariana-maillog__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .6rem;
    margin-bottom: .6rem;
}

.ariana-maillog__badge {
    padding: .15rem .55rem;
    border-radius: 999px;
    font-size: .7rem;
    font-weight: 500;
    letter-spacing: .03em;
    text-transform: uppercase;
}

.ariana-maillog__badge.is-ok  { background: rgba(34, 197, 94, .16);  color: var(--ar-success-ink); }
.ariana-maillog__badge.is-bad { background: rgba(239, 68, 68, .16);  color: var(--ar-danger-ink); }

.ariana-maillog__stage { color: var(--ar-ink); font-weight: 500; }
.ariana-maillog__time  { margin-inline-start: auto; color: var(--ar-ink-mute); font-size: .75rem; }

.ariana-maillog__summary {
    margin: 0 0 .75rem;
    line-height: 1.6;
    color: var(--ar-ink);
}

.ariana-maillog__hint {
    display: flex;
    gap: .55rem;
    padding: .7rem .8rem;
    margin-bottom: .85rem;
    border-radius: 8px;
    border: 1px solid rgba(245, 158, 11, .3);
    background: var(--ar-warning-bg);
    line-height: 1.6;
    color: var(--ar-warning-ink);
}

.ariana-maillog__hinticon { width: 1rem; height: 1rem; flex: 0 0 auto; margin-top: .15rem; color: var(--ariana-warning); }

.ariana-maillog__block { margin-top: .85rem; }

.ariana-maillog__label {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .5rem;
    margin-bottom: .35rem;
    font-size: .72rem;
    font-weight: 500;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--ar-ink-mute);
}

.ariana-maillog__note { text-transform: none; letter-spacing: 0; font-weight: 400; opacity: .75; }

.ariana-maillog__grid {
    display: grid;
    grid-template-columns: minmax(6rem, auto) 1fr;
    gap: .2rem .9rem;
    margin: 0;
}

.ariana-maillog__grid dt { color: var(--ar-ink-dim); }
.ariana-maillog__grid dd { margin: 0; color: var(--ar-ink); word-break: break-all; }

.ariana-maillog__errors {
    margin: 0;
    padding-inline-start: 1.25rem;
    list-style: disc outside;
    line-height: 1.6;
    color: var(--ar-danger-ink);
}

.ariana-maillog__errors li { margin-bottom: .2rem; word-break: break-word; }

/* The transcript is the one place a horizontal scrollbar is correct: wrapping
   an SMTP line would break the > / < alignment that makes it readable. */
.ariana-maillog__pre {
    margin: 0;
    max-height: 22rem;
    overflow: auto;
    padding: .75rem;
    border-radius: 8px;
    border: 1px solid var(--ar-line);
    background: var(--ar-sunken);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .72rem;
    line-height: 1.55;
    white-space: pre;
    color: var(--ar-ink);
}

/* The publish-box action row: full width, primary first, cancel quiet. */
.ariana-publish-actions {
    padding-top: .35rem;
    border-top: 1px solid var(--ar-line);
    margin-top: .25rem;
}

/* ===========================================================================
   12. Table header band, and theme screenshots

      THE HEADER BAND
      Filament gives the actions column a <th> with the classes
      `fi-ta-actions-header-cell fi-ta-empty-header-cell` - note that it does
      NOT carry `fi-ta-header-cell`. Any rule written against that class
      therefore skips it, and the header reads as a bar that stops short of the
      table's right edge, with a bare gap above the row buttons.

      So the band is painted on the ROW, not on the labelled cells. Every <th>
      is covered including the unlabelled one, and it stays covered if Filament
      renames a cell class.
   ======================================================================== */

.fi-ta-table > thead > tr > th {
    background-color: var(--ar-sunken);
    border-bottom: 1px solid var(--ar-line);
}

.dark .fi-ta-table > thead > tr > th {
    background-color: rgba(255, 255, 255, .035);
}

/* Filament sizes the empty actions header to 4px, which is fine when nothing is
   painted on it and wrong once something is. It takes its width from the row
   buttons beneath it instead. */
.fi-ta-table > thead > tr > th.fi-ta-empty-header-cell {
    width: auto;
    min-width: 0;
}

/* Round the band with the card ONLY when it is actually the top of the card.
   Filament marks such a table `fi-ta-ctn-with-header`, but that class tracks the
   table's heading rather than its toolbar, so the presence of a toolbar is also
   tested directly. Either one means the header row is a middle band, and
   rounding it there produced curved corners sitting under a straight-edged bar
   — which is what made the list pages look unfinished. */
.fi-ta-ctn:not(.fi-ta-ctn-with-header):not(:has(.fi-ta-header-ctn)) .fi-ta-table > thead > tr > th:first-child {
    border-start-start-radius: var(--ariana-r-lg, 12px);
}

.fi-ta-ctn:not(.fi-ta-ctn-with-header):not(:has(.fi-ta-header-ctn)) .fi-ta-table > thead > tr > th:last-child {
    border-start-end-radius: var(--ariana-r-lg, 12px);
}

/* ---- 12b. Resource tabs joined to the table card -------------------------
   A list page rendered three stacked bars: the status tabs, the search and
   filter toolbar, and the header row — three separate slabs, only some of them
   rounded, with a grid gap between the first two. They are one control surface
   and now read as one card.

   The DOM does not co-operate: the tabs live in their own grid column
   (.fi-sc-tabs) and the table in the next one, so they cannot simply be given
   one border. Instead the tabs become the card's TOP segment — rounded above,
   square below, bottom border removed — and the table card below it drops its
   own top rounding and pulls up to meet it. The seam disappears and the two
   read as a single panel.

   Scoping matters more than it looks. `.fi-sc-tabs` is the generic schema tabs
   component: the Settings form uses it too. Scoping this to `.fi-page-content`
   therefore caught Settings as well, and the negative margin that closes the
   seam on a list page pulled the Save button up onto the card there (1.13.1).
   The rules are keyed on the resource LIST page instead, so the Settings form,
   the post editor's SEO/Advanced box and every other tab strip are untouched.
   ======================================================================== */

.fi-resource-list-records-page:has(.fi-sc-tabs) .fi-sc-tabs {
    background-color: var(--ar-sunken);
    border: 1px solid var(--ar-line);
    border-bottom: 0;
    border-start-start-radius: var(--ariana-r-lg, 12px);
    border-start-end-radius: var(--ariana-r-lg, 12px);
    border-end-start-radius: 0;
    border-end-end-radius: 0;
    padding-inline: .25rem;
}

.dark .fi-resource-list-records-page:has(.fi-sc-tabs) .fi-sc-tabs {
    background-color: rgba(255, 255, 255, .035);
    border-color: var(--ariana-purple-line);
}

/* Close the grid gap between the two columns so the segments meet. Filament's
   schema grid uses `gap: calc(var(--spacing) * 6)` with --spacing: .25rem, so
   the gap is read from its own variables rather than hard-coded: if Filament
   retunes its spacing scale, the seam follows instead of splitting open. */
.fi-resource-list-records-page:has(.fi-sc-tabs) .fi-sc-tabs {
    margin-bottom: calc(var(--spacing, .25rem) * -6);
}

/* The card is no longer the top of the stack. */
.fi-resource-list-records-page:has(.fi-sc-tabs) .fi-ta-ctn {
    border-start-start-radius: 0;
    border-start-end-radius: 0;
}

/* One line between the tabs and the toolbar, not two. The toolbar sits inside
   .fi-ta-main rather than directly in the card, so this is a descendant rule —
   checked against the rendered page, not assumed from the template. */
.fi-resource-list-records-page:has(.fi-sc-tabs) .fi-ta-ctn .fi-ta-header-ctn {
    border-top: 0;
}

/* The tab strip itself carries no second background now that its wrapper is
   the segment; and its items sit on the seam rather than floating above it. */
.fi-resource-list-records-page:has(.fi-sc-tabs) .fi-tabs {
    background-color: transparent;
    border: 0;
    box-shadow: none;
}

/* ---- Theme screenshots --------------------------------------------------- */

.ariana-themeshot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 96px;
    height: 64px;
    border-radius: var(--ariana-r-md, 8px);
    border: 1px solid var(--ar-line);
    background: var(--ar-sunken);
    object-fit: cover;
    overflow: hidden;
}

.ariana-themeshot--empty {
    color: var(--ar-ink-mute);
}

.ariana-themeshot--empty svg {
    width: 1.6rem;
    height: 1.6rem;
}

/* ===========================================================================
   13. Light mode — "violet paper"
       Ariana's dark panel is a deep indigo-violet. Light mode is the same
       violet lit from the front: violet-tinted neutrals rather than grey, a
       darker violet accent so it can carry white text and pass AA as link
       text, and a deep violet-black ink so nothing on screen is a colour from
       outside the family.

       Scoped with :root:not(.dark) rather than left unscoped, because Filament
       toggles `dark` on <html>. An unscoped rule would bleed into the dark
       panel and undo the theme above.

       DELIBERATELY NOT a dark sidebar on a light page. Someone who switches to
       light mode wants a light interface; handing back a dark slab defeats the
       reason they switched, and it becomes a third theme to maintain that
       fights the topbar for attention.
   ======================================================================== */

/* ---- 13.1 Canvas and chrome --------------------------------------------- */

:root:not(.dark) body,
:root:not(.dark) .fi-body,
:root:not(.dark) .fi-main-ctn {
    background-color: var(--ar-canvas);
    color: var(--ar-ink);
}

:root:not(.dark) .fi-sidebar,
:root:not(.dark) .fi-sidebar-nav,
:root:not(.dark) .fi-sidebar-header {
    background-color: var(--ar-chrome);
    border-color: var(--ar-line);
}

:root:not(.dark) .fi-topbar,
:root:not(.dark) .fi-topbar > nav,
:root:not(.dark) .fi-topbar nav.fi-topbar-nav {
    background-color: var(--ar-surface);
    border-bottom: 1px solid var(--ar-line);
}

/* Section headings in the sidebar: quiet, but not so quiet they stop grouping. */
:root:not(.dark) .fi-sidebar-group-label {
    color: var(--ar-ink-mute);
    letter-spacing: .06em;
}

:root:not(.dark) .fi-sidebar-item-label {
    color: var(--ar-ink-dim);
}

:root:not(.dark) .fi-sidebar-item-button:hover {
    background-color: var(--ar-sunken);
}

:root:not(.dark) .fi-sidebar-item-button:hover .fi-sidebar-item-label {
    color: var(--ar-ink);
}

/* The active item. The dark panel marks it with a glow; on paper the same job
   is done by an accent wash and a solid left edge - a border reads at a glance
   where a background tint alone can be missed. */
:root:not(.dark) .fi-sidebar-item-active > .fi-sidebar-item-button {
    background-color: var(--ar-wash);
    box-shadow: inset 3px 0 0 0 var(--ar-accent);
}

:root:not(.dark) .fi-sidebar-item-active .fi-sidebar-item-label {
    color: var(--ar-accent-ink);
    font-weight: 600;
}

:root:not(.dark) .fi-sidebar-item-active .fi-icon {
    color: var(--ar-accent-ink);
}

/* ---- 13.2 Cards and content -------------------------------------------- */

:root:not(.dark) .fi-section,
:root:not(.dark) .fi-ta-ctn,
:root:not(.dark) .fi-wi-stats-overview-stat,
:root:not(.dark) .fi-dropdown-panel,
:root:not(.dark) .fi-modal-window {
    background-color: var(--ar-surface);
    border-color: var(--ar-line);
}

:root:not(.dark) .fi-section-header,
:root:not(.dark) .fi-ta-header-ctn {
    border-color: var(--ar-line);
}

:root:not(.dark) .fi-header-heading,
:root:not(.dark) .fi-section-header-heading,
:root:not(.dark) .fi-ta-header-heading,
:root:not(.dark) .fi-modal-heading {
    color: var(--ar-ink);
}

:root:not(.dark) .fi-header-subheading,
:root:not(.dark) .fi-section-header-description,
:root:not(.dark) .fi-ta-empty-state-description,
:root:not(.dark) .fi-fo-field-wrp-helper-text,
:root:not(.dark) .fi-fo-field-wrp-hint {
    color: var(--ar-ink-mute);
}

:root:not(.dark) .fi-breadcrumbs-item-label {
    color: var(--ar-ink-mute);
}

:root:not(.dark) .fi-breadcrumbs-item:last-child .fi-breadcrumbs-item-label {
    color: var(--ar-ink-dim);
}

/* ---- 13.3 Tables -------------------------------------------------------- */

:root:not(.dark) .fi-ta-header-cell,
:root:not(.dark) .fi-ta-col-label {
    color: var(--ar-ink-dim);
}

:root:not(.dark) .fi-ta-cell {
    color: var(--ar-ink);
}

:root:not(.dark) .fi-ta-row:hover {
    /* A 7.8% luminance step: findable while tracking across a wide row, and
       quiet enough that scrolling a long list is not a strobe. */
    background-color: #F7F5FD;
}

:root:not(.dark) .fi-ta-row + .fi-ta-row {
    border-top-color: var(--ar-line);
}

/* ---- 13.4 Inputs -------------------------------------------------------- */

:root:not(.dark) .fi-input-wrp,
:root:not(.dark) .fi-fo-field-wrp .fi-input-wrp {
    background-color: var(--ar-surface);
    border-color: var(--ar-line-strong);
}

:root:not(.dark) .fi-input-wrp:focus-within {
    border-color: var(--ar-accent);
    box-shadow: 0 0 0 3px var(--ar-ring);
}

:root:not(.dark) .fi-input,
:root:not(.dark) .fi-fo-select select,
:root:not(.dark) textarea {
    color: var(--ar-ink);
}

:root:not(.dark) .fi-input::placeholder,
:root:not(.dark) textarea::placeholder {
    color: var(--ar-ink-mute);
}

:root:not(.dark) .fi-fo-field-wrp-label,
:root:not(.dark) .fi-in-entry-label {
    color: var(--ar-ink-dim);
}

/* ---- 13.5 Tabs ---------------------------------------------------------- */

:root:not(.dark) .fi-tabs {
    background-color: var(--ar-sunken);
}

:root:not(.dark) .fi-tabs-item-label {
    color: var(--ar-ink-dim);
}

:root:not(.dark) .fi-tabs-item-active,
:root:not(.dark) .fi-tabs-item[aria-selected="true"] {
    background-color: var(--ar-surface);
    box-shadow: 0 1px 2px rgba(27, 20, 54, .08);
}

:root:not(.dark) .fi-tabs-item-active .fi-tabs-item-label,
:root:not(.dark) .fi-tabs-item[aria-selected="true"] .fi-tabs-item-label {
    color: var(--ar-accent-ink);
    font-weight: 600;
}

/* ---- 13.6 Stats widgets ------------------------------------------------- */

:root:not(.dark) .fi-wi-stats-overview-stat-label {
    color: var(--ar-ink-mute);
}

:root:not(.dark) .fi-wi-stats-overview-stat-value {
    color: var(--ar-ink);
}

:root:not(.dark) .fi-wi-stats-overview-stat-description {
    color: var(--ar-ink-dim);
}

/* ---- 13.7 Prose and links ---------------------------------------------- */

:root:not(.dark) .fi-prose,
:root:not(.dark) .fi-fo-rich-editor-content {
    color: var(--ar-ink);
}

:root:not(.dark) .fi-prose :is(h1, h2, h3, h4) {
    color: var(--ar-ink);
}

:root:not(.dark) .fi-prose a,
:root:not(.dark) .fi-link-label {
    color: var(--ar-accent-ink);
}

/* ---- 13.8 The brand wordmark ------------------------------------------- */

:root:not(.dark) .ariana-brand__word {
    color: var(--ar-ink);
}

/* ---- 13.9 Keyboard focus ----------------------------------------------- */

:root:not(.dark) :focus-visible {
    outline-color: var(--ar-accent);
}

/* ===========================================================================
   AI credit card — the dashboard's only money figure.
   Sized to sit beside "Needs attention" as an equal, not as a stray stat.
   ======================================================================== */

/* EQUAL HEIGHT, NOT MERELY ADJACENT
   Two widgets sharing a dashboard row must end at the same line. Filament's
   grid items already stretch, but a section only fills the cell if it is
   told to — so the card is a full-height column and its body pushes the
   footer note to the bottom. */
.fi-wi-widget { block-size: 100%; }
.fi-wi-widget > .fi-section { block-size: 100%; }

.ariana-credit {
    display: flex;
    flex-direction: column;
    gap: .45rem;
    block-size: 100%;
}

.ariana-credit__spacer { flex: 1 1 auto; min-block-size: .25rem; }

.ariana-credit__figure {
    font-size: 1.75rem;
    font-weight: 700;
    line-height: 1.1;
    margin: 0;
}

.ariana-credit__figure--good  { color: #4ade80; }
.ariana-credit__figure--warn  { color: #fbbf24; }
.ariana-credit__figure--bad   { color: #f87171; }
.ariana-credit__figure--neutral { color: #efeaff; }
.ariana-credit__figure--muted { color: rgba(239, 234, 255, .55); font-size: 1.4rem; }

.ariana-credit__meta { margin: 0; font-size: .78rem; opacity: .68; }
.ariana-credit__hint { margin: .2rem 0 0; font-size: .72rem; opacity: .55; line-height: 1.5; }
.ariana-credit__label { font-size: .78rem; opacity: .75; }

.ariana-credit__entry {
    display: flex;
    align-items: center;
    gap: .35rem;
    border-radius: .65rem;
    border: 1px solid rgba(124, 108, 255, .35);
    padding-inline: .6rem;
    background: rgba(124, 108, 255, .06);
}

.ariana-credit__currency { opacity: .6; font-size: .9rem; }

.ariana-credit__input {
    flex: 1;
    min-inline-size: 0;
    border: 0;
    background: transparent;
    padding-block: .5rem;
    font-size: 1rem;
    color: inherit;
}

.ariana-credit__input:focus { outline: none; }

.ariana-credit__actions { display: flex; gap: .4rem; }

.ariana-credit__save {
    border: 0;
    cursor: pointer;
    border-radius: .6rem;
    background: #7c6cff;
    color: #fff;
    font-size: .78rem;
    font-weight: 600;
    padding: .45rem .8rem;
    align-self: flex-start;
}

.ariana-credit__save:hover { background: #6b59ff; }

.ariana-credit__cancel,
.ariana-credit__link {
    border: 0;
    background: transparent;
    cursor: pointer;
    color: inherit;
    opacity: .65;
    font-size: .78rem;
    padding: .45rem .2rem;
    align-self: flex-start;
    text-align: start;
}

.ariana-credit__cancel:hover,
.ariana-credit__link:hover { opacity: 1; text-decoration: underline; }

/* ==========================================================================
   Media library — grid layout, video tiles and the file preview dialog
   (1.48.0)

   Every rule here uses logical properties (inline-start/end, margin-inline,
   text-align: start) rather than left/right, so the whole of it mirrors in
   Persian and the other RTL locales without a second stylesheet — the same
   rule the media picker above already follows.
   ========================================================================== */

/* --- the picker's non-image tiles ---------------------------------------- */

/* A video with no poster frame, or any file that is not a picture. The sheet
   fills the same square an <img> would, so a mixed grid stays on one baseline
   instead of stepping up and down row by row. */
.ariana-mediapicker__tile-sheet {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    aspect-ratio: 1 / 1;
    background: var(--ar-sunken);
    color: var(--ar-ink-dim);
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .06em;
}

/* The play glyph is centred on the artwork, not on the whole tile: the tile
   also holds the filename strip underneath, and centring on that would sit the
   triangle low and off the picture. */
.ariana-mediapicker__tile-play,
.ariana-mediagrid__play {
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    /* Matches the 1/1 artwork box above the name strip. */
    aspect-ratio: 1 / 1;
    font-size: 1.5rem;
    color: #fff;
    text-shadow: 0 1px 6px rgba(0, 0, 0, .55);
    pointer-events: none;
}

.ariana-mediapicker__preview video {
    display: block;
    width: 100%;
    max-height: 190px;
    background: #000;
}

.ariana-mediapicker__preview audio {
    display: block;
    width: 100%;
    padding: .75rem;
}

/* --- the library grid ---------------------------------------------------- */

/*  THE CELL, NOT JUST THE CARD
    Filament wraps every grid record in its own chrome: a `.fi-ta-record` with
    padding and a border, a selection checkbox rendered as a "content prefix"
    that shifts the content sideways, and a `<button>` wrapper around the
    clickable area. 1.48.1 styled only the card INSIDE that chrome, so the card
    was offset by the checkbox, overflowed the record's right edge, and every
    card ended up a different height.

    So the record itself becomes the card. Its chrome is neutralised here in one
    place rather than worked around inside the Blade, and the card partial stays
    a plain, self-contained piece of markup.                                   */

.fi-ta-content-grid > .fi-ta-record {
    position: relative;
    display: flex;
    flex-direction: column;
    /* Equal height across a row regardless of how long a filename runs or
       whether a card carries the "no ALT text" line. */
    height: 100%;
    padding: 0;
    overflow: hidden;
    border-radius: 12px;
    border: 1px solid var(--ar-line);
    background: var(--ar-sunken);
}

/* The checkbox is a content prefix, which shifts everything after it inline.
   Taken out of flow and floated over the artwork instead. */
.fi-ta-content-grid > .fi-ta-record > .fi-ta-record-checkbox {
    position: absolute;
    inset-block-start: .45rem;
    inset-inline-start: .45rem;
    z-index: 2;
    margin: 0;
}

/* Flex column all the way down, not block.
   The height has to be handed from the grid item to the card, or the card stops
   at its content and the action bar of a card with a "no ALT text" line sits a
   line lower than its neighbour's. A flex column also stretches its children to
   full width, so this carries the horizontal fix as well. */
/* The action bar is a CHILD of the content container, not a sibling of it, so
   the container is what has to place it: one row that takes the space left
   over, then one that takes what it needs. `grid-template-rows: 1fr auto` says
   that outright, where a flex chain left the leftover space distributed between
   the card and the bar and the bars in a row ended up at different heights. */
.fi-ta-content-grid > .fi-ta-record > .fi-ta-record-content-ctn {
    display: grid;
    grid-template-rows: 1fr auto;
    gap: 0;
    padding: 0;
    width: 100%;
    min-width: 0;
    min-height: 0;
    flex: 1 1 auto;
}

/* Every wrapper from here down is a single full-height row, so the card
   inherits the whole cell instead of stopping at its own content. */
.fi-ta-content-grid > .fi-ta-record > .fi-ta-record-content-ctn > div,
.fi-ta-content-grid .fi-ta-record-content > .fi-grid-col,
.fi-ta-content-grid .fi-ta-stack,
.fi-ta-content-grid .fi-ta-stack > .fi-grid-col,
.fi-ta-content-grid .fi-ta-col {
    display: grid;
    grid-template-rows: 1fr;
    /* minmax(0, 1fr), not an implicit auto column. An auto track sizes to its
       CONTENT, so the card came out as wide as whatever image was inside it —
       82px for a small logo, 152px for a photograph — and a row of cards was
       never uniform. minmax(0, …) also lets the track shrink below the
       content's minimum, which is what stops a wide image forcing it open. */
    grid-template-columns: minmax(0, 1fr);
    align-content: stretch;
    /* Filament's stack carries fi-align-start, which stops its children
       stretching. Restated here, or the card sizes to its content. */
    justify-items: stretch;
    align-items: stretch;
    width: 100%;
    min-width: 0;
    min-height: 0;
    max-width: none;
    gap: 0;
}

/* The clickable wrapper is a <button>: it arrives with button padding, centred
   text and a fixed intrinsic width. All three have to go. */
.fi-ta-content-grid .fi-ta-record-content {
    display: grid;
    grid-template-rows: 1fr;
    height: 100%;
    width: 100%;
    padding: 0;
    margin: 0;
    border: 0;
    background: transparent;
    text-align: start;
    cursor: pointer;
}

/* The sort keys are rendered because Filament only sorts by a VISIBLE column,
   but they must occupy nothing. Hiding the inner element alone left three empty
   column wrappers stacked under every card. */
.ariana-mediagrid__sortkey,
.fi-ta-content-grid .fi-ta-col:has(> .ariana-mediagrid__sortkey) {
    display: none;
}

.ariana-mediagrid__card {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    /* Explicit, not inherited. A percentage width resolves against a parent
       with a definite width; leaving the card to stretch implicitly is what
       let a 1694px-wide photograph size its own card and burst the frame. */
    width: 100%;
    max-width: 100%;
    min-width: 0;
    justify-self: stretch;
    /* No border or background of its own: the record cell above provides both,
       and two nested frames read as a mistake. */
}

.ariana-mediagrid__art {
    position: relative;
    /* A fixed square, so a row of cards is level whatever shape the files are.
       flex-shrink: 0 keeps it square when the card is stretched taller than its
       content by a neighbour with a longer name. */
    aspect-ratio: 1 / 1;
    flex: 0 0 auto;
    width: 100%;
    /* The cap is what actually contains an oversized image: without it the box
       takes the picture's intrinsic width and the aspect ratio makes it that
       tall as well. */
    max-width: 100%;
    min-width: 0;
    background: color-mix(in srgb, var(--ar-line) 35%, transparent);
    overflow: hidden;
}

.ariana-mediagrid__image {
    display: block;
    width: 100%;
    height: 100%;
    /* cover, so a portrait photograph and a landscape one fill the same box.
       A small image is scaled up rather than left as a stamp in the corner. */
    object-fit: cover;
}

.ariana-mediagrid__sheet {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
}

.ariana-mediagrid__duration {
    position: absolute;
    inset-block-end: .35rem;
    inset-inline-end: .35rem;
    padding: .1rem .35rem;
    border-radius: 5px;
    background: rgba(0, 0, 0, .72);
    color: #fff;
    font-size: .66rem;
    font-variant-numeric: tabular-nums;
    line-height: 1.4;
}

.ariana-mediagrid__badge {
    position: absolute;
    inset-block-start: .4rem;
    inset-inline-end: .4rem;
    padding: .1rem .38rem;
    border-radius: 5px;
    font-size: .62rem;
    font-weight: 600;
    line-height: 1.5;
    color: #fff;
}

.ariana-mediagrid__badge--busy { background: #6b7280; }
.ariana-mediagrid__badge--bad  { background: #b91c1c; }
.ariana-mediagrid__badge--warn { background: #b45309; }

.ariana-mediagrid__body {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    padding: .5rem .6rem;
    flex: 1 1 auto;
    min-width: 0;
}

.ariana-mediagrid__name {
    margin: 0;
    font-size: .78rem;
    font-weight: 600;
    line-height: 1.35;
    color: var(--ar-ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: start;
}

.ariana-mediagrid__meta {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
    margin: 0;
    font-size: .66rem;
    line-height: 1.5;
    color: var(--ar-ink-dim);
    text-align: start;
}

.ariana-mediagrid__meta span + span::before {
    content: "\00b7";
    margin-inline-end: .3rem;
}

.ariana-mediagrid__alt {
    margin: 0;
    font-size: .66rem;
    line-height: 1.5;
    color: var(--ar-warning-ink, #f59e0b);
    text-align: start;
}

/* The action bar: one menu button, pinned to the bottom edge of the card so
   the bars line up across a row even when the names above them wrap. */
.fi-ta-content-grid .fi-ta-actions {
    display: flex;
    flex: 0 0 auto;
    width: 100%;
    margin: 0;
    padding: .45rem .6rem;
    border-block-start: 1px solid var(--ar-line);
    /* end, not flex-end: the bar has to mirror in Persian like everything
       else on this screen. */
    justify-content: end;
}

/* --- the preview dialog -------------------------------------------------- */

.ariana-filemodal {
    display: flex;
    flex-direction: column;
    gap: .85rem;
}

.ariana-filemodal__stage {
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 12px;
    border: 1px solid var(--ar-line);
    background: var(--ar-sunken);
    overflow: hidden;
    padding: .5rem;
}

.ariana-filemodal__video {
    display: block;
    width: 100%;
    max-height: 62vh;
    background: #000;
    border-radius: 8px;
}

.ariana-filemodal__audio { width: 100%; }

.ariana-filemodal__image {
    display: block;
    max-width: 100%;
    max-height: 62vh;
    object-fit: contain;
    border-radius: 8px;
}

.ariana-filemodal__facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: .5rem .9rem;
    margin: 0;
}

.ariana-filemodal__facts dt {
    font-size: .66rem;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--ar-ink-dim);
    text-align: start;
}

.ariana-filemodal__facts dd {
    margin: 0;
    font-size: .8rem;
    color: var(--ar-ink);
    word-break: break-word;
    text-align: start;
}

.ariana-filemodal__note {
    margin: 0;
    padding: .5rem .65rem;
    border-radius: 8px;
    border-inline-start: 3px solid var(--ar-warning-ink, #f59e0b);
    background: rgba(245, 158, 11, .08);
    font-size: .76rem;
    line-height: 1.6;
    color: var(--ar-ink-dim);
    text-align: start;
}

.ariana-filemodal__url {
    display: flex;
    flex-direction: column;
    gap: .3rem;
    font-size: .7rem;
    color: var(--ar-ink-dim);
    text-align: start;
}

.ariana-filemodal__urlrow {
    display: flex;
    gap: .4rem;
    align-items: stretch;
}

/* Sibling controls share height, radius and border by declaring them once for
   both. The input and the button are different elements with different default
   box models, and letting each keep its own is exactly how a two-pixel
   misalignment appears in a row like this. */
.ariana-filemodal__urlrow input,
.ariana-filemodal__copy {
    height: 2.3rem;
    box-sizing: border-box;
    border-radius: 8px;
    border: 1px solid var(--ar-line);
    font-size: .78rem;
    line-height: 1.4;
}

.ariana-filemodal__urlrow input {
    flex: 1 1 auto;
    min-width: 0;
    padding-inline: .6rem;
    background: var(--ar-sunken);
    color: var(--ar-ink);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    text-align: start;
    /* URLs are read left-to-right even in a mirrored panel. */
    direction: ltr;
}

.ariana-filemodal__copy {
    flex: 0 0 auto;
    padding-inline: .85rem;
    cursor: pointer;
    background: var(--ar-accent);
    border-color: var(--ar-accent);
    color: #fff;
    font-weight: 600;
    white-space: nowrap;
}

.ariana-filemodal__copy:hover { filter: brightness(1.08); }

/* The grid's sort keys.
   Filament only offers — and only APPLIES — a sort for a column that is both
   sortable and visible, and a grid has no column headers to click. So the
   three sortable columns are rendered into every card and hidden here: the
   card already shows the name, the size and the date, and repeating them would
   be noise. display:none also removes them from the accessibility tree, which
   is correct — they carry no information the card does not already announce. */
.ariana-mediagrid__sortkey { display: none; }

/* ==========================================================================
   The video quality / encoding speed sliders (Settings → Media)

   Two matched controls on one line, each carrying a labelled scale.

   The track is FLUSH with its label and with every other control on the
   screen — no inset. An earlier attempt indented it to make room for the end
   labels, which fixed the overflow and broke the alignment: the track no
   longer started where its own label did, or where the text input below it
   did, and that reads as sloppier than the problem it solved.

   Instead the two END labels are clamped. noUiSlider centres every label on
   its value (`transform: translate(-50%, 50%)`), so the ones at 0% and 100%
   hang half their own width past the track. Those two are re-anchored to the
   inside — the only two that can overflow, and the only two that are touched.
   The hook is the inline `left: 0%` / `left: 100%` noUiSlider writes itself.
   ========================================================================== */

.ariana-videoslider {
    /* The scale is absolutely positioned and contributes no height of its own;
       without this the helper sentence underneath sits on top of it. */
    margin-block-end: 2rem;
}

.ariana-videoslider .noUi-value {
    font-size: .625rem;
    line-height: 1.4;
    letter-spacing: .01em;
    color: var(--ar-ink-dim);
    white-space: nowrap;
}

/* The two labels that would otherwise leave the field. The Y half of the
   transform repeats Filament's own (translate(-50%, 50%)); only the X anchor
   changes, so the scale keeps sitting exactly where the rest of it sits. */
.ariana-videoslider .noUi-value[style*="left: 0%"] {
    transform: translate(0, 50%);
}

.ariana-videoslider .noUi-value[style*="left: 100%"] {
    transform: translate(-100%, 50%);
}

/* RTL: Filament flips the base anchor to translate(50%, 50%), so the two ends
   swap which side they would overflow on. */
[dir="rtl"] .ariana-videoslider .noUi-value[style*="left: 0%"] {
    transform: translate(0, 50%);
}

[dir="rtl"] .ariana-videoslider .noUi-value[style*="left: 100%"] {
    transform: translate(-100%, 50%);
}

/* Tick marks: shorter and quieter than the noUiSlider default, which is drawn
   for a light background and reads as heavy on the panel's deep purple. */
.ariana-videoslider .noUi-marker {
    background: color-mix(in srgb, currentColor 28%, transparent);
}

.ariana-videoslider .noUi-marker-large {
    height: 8px;
    background: color-mix(in srgb, currentColor 45%, transparent);
}

.ariana-videoslider .noUi-marker-normal {
    height: 4px;
}

@media (max-width: 640px) {
    .ariana-videoslider {
        margin-block-end: 1.85rem;
    }

    .ariana-videoslider .noUi-value {
        font-size: .58rem;
    }
}

/* ==========================================================================
   THE WORKING MARK — one spinner for every wait in Ariana
   ==========================================================================

   Every surface that waits on an AI provider already had a progress bar, and
   a progress bar is a poor answer to the only question an operator actually
   asks while waiting: "is this still alive, or has it hung?" A bar that has
   not moved for twenty seconds looks exactly like a bar that never will —
   and podcast generation legitimately pauses for a minute at a time when the
   speech service asks it to.

   So: one mark, used identically on the Assistant, Auto Pilot, Podcasts, the
   SEO Analyzer and the article's audio dialog. It turns while work is in
   flight and stops the moment the work does — a failed run renders a
   different block entirely, and a browser that has gone offline is caught by
   `wire:offline.class`, which is the one case where the page cannot know
   that nothing is happening any more.

   Motion is opt-out: under prefers-reduced-motion the mark holds still and
   dims instead, so the same markup still says "working" without moving. */

@keyframes ariana-working-spin {
    to { transform: rotate(360deg); }
}

@keyframes ariana-working-pulse {
    50% { opacity: .35; }
}

.ariana-working-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 1.1em;
    block-size: 1.1em;
    flex: 0 0 auto;
    color: rgb(124, 108, 255);
    vertical-align: -.15em;
}

.ariana-working-mark svg {
    inline-size: 100%;
    block-size: 100%;
    animation: ariana-working-spin 1.1s linear infinite;
    transform-origin: 50% 50%;
}

/* A Filament section can carry the same meaning through its own icon. */
.ariana-working .fi-section-header-icon svg,
.ariana-working .fi-icon svg {
    animation: ariana-working-spin 1.1s linear infinite;
    transform-origin: 50% 50%;
}

/* Offline: the poll cannot reach the server, so nothing is progressing and
   the mark must stop claiming otherwise. Applied by wire:offline.class. */
.ariana-working-mark--stalled svg,
.ariana-working--stalled .fi-section-header-icon svg {
    animation: none;
    opacity: .4;
}

.ariana-working-offline {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font-size: .75rem;
    font-weight: 600;
    color: #D97706;
}

@media (prefers-reduced-motion: reduce) {
    .ariana-working-mark svg,
    .ariana-working .fi-section-header-icon svg,
    .ariana-working .fi-icon svg {
        animation: ariana-working-pulse 1.8s ease-in-out infinite;
    }
}

/* ---------------------------------------------------------------------------
 * Site health (System → Site health) — one glanceable table.
 *
 * The first version stacked seven Filament sections and read as a wall of
 * prose; the owner's verdict was that a person should see what is fine and
 * what is broken in one look, with the remedy unmistakable. So: a table with
 * a colour-coded status column, problems sorted first, and each remedy in
 * its own tinted "How to fix" strip under its row — steps numbered, the cron
 * line rendered exactly once as selectable code.
 *
 * Everything is drawn with the --ar-* semantic tokens above, so both modes
 * come for free; the status tints are color-mix washes of the ink tokens so
 * no literal hex can drift out of the palette. Logical properties for RTL.
 * ------------------------------------------------------------------------- */
.ariana-health__summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    margin-block-end: 1rem;
}

.ariana-health__summary-actions {
    display: flex;
    gap: .5rem;
    margin-inline-start: auto;
}

/* ---- Site health: page status (the UrlAudit tiles and their modals) ---- */

.ariana-audit { margin-block-end: 1.5rem; }

.ariana-audit__tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
    gap: .75rem;
}

/* Filament wraps a modal's trigger in its own div, so the button has to
   be told to fill the grid cell — or the clickable tiles come out narrower
   than the plain ones beside them (measured, 1.67.0). */
.ariana-audit__tiles .fi-modal-trigger { display: block; block-size: 100%; }

.ariana-audit__tile {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: .1rem;
    inline-size: 100%;
    block-size: 100%;
    padding: .8rem .95rem;
    border: 1px solid var(--ar-line);
    border-radius: .75rem;
    background: var(--ar-surface);
    color: var(--ar-ink);
    text-align: start;
    font: inherit;
}

.ariana-audit__tile--opens { cursor: pointer; transition: border-color .15s ease, transform .15s ease; }
.ariana-audit__tile--opens:hover { border-color: var(--ar-ink-mute); transform: translateY(-1px); }

.ariana-audit__count { font-size: 1.5rem; font-weight: 700; line-height: 1.1; }

.ariana-audit__label {
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
}

.ariana-audit__caption { font-size: .72rem; color: var(--ar-ink-mute); }

.ariana-audit__tile--quiet .ariana-audit__count,
.ariana-audit__tile--quiet .ariana-audit__label { color: var(--ar-ink-mute); }

.ariana-audit__tile--ok {
    border-color: color-mix(in srgb, var(--ar-success-ink) 45%, transparent);
    background: color-mix(in srgb, var(--ar-success-ink) 7%, var(--ar-surface));
}
.ariana-audit__tile--ok .ariana-audit__count { color: var(--ar-success-ink); }

.ariana-audit__tile--warning {
    border-color: color-mix(in srgb, var(--ar-warning-ink) 45%, transparent);
    background: color-mix(in srgb, var(--ar-warning-ink) 7%, var(--ar-surface));
}
.ariana-audit__tile--warning .ariana-audit__count { color: var(--ar-warning-ink); }

.ariana-audit__tile--problem {
    border-color: color-mix(in srgb, var(--ar-danger-ink) 45%, transparent);
    background: color-mix(in srgb, var(--ar-danger-ink) 7%, var(--ar-surface));
}
.ariana-audit__tile--problem .ariana-audit__count { color: var(--ar-danger-ink); }

.ariana-audit__hint,
.ariana-audit__more {
    margin: .75rem 0 0;
    font-size: .8rem;
    color: var(--ar-ink-mute);
}

.ariana-audit__codes {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem 1rem;
    margin: 0 0 .75rem;
    font-size: .8rem;
    color: var(--ar-ink-dim);
}

.ariana-audit__listwrap {
    max-block-size: 60vh;
    overflow: auto;
    border: 1px solid var(--ar-line);
    border-radius: .5rem;
}

.ariana-audit__list {
    width: 100%;
    border-collapse: collapse;
    font-size: .82rem;
    color: var(--ar-ink);
}

.ariana-audit__list th,
.ariana-audit__list td {
    padding: .45rem .7rem;
    text-align: start;
    border-block-end: 1px solid var(--ar-line);
    vertical-align: top;
}

.ariana-audit__list thead th {
    position: sticky;
    inset-block-start: 0;
    background: var(--ar-surface);
    font-size: .72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--ar-ink-mute);
}

.ariana-audit__list tbody tr:last-child td { border-block-end: 0; }

.ariana-audit__url { word-break: break-all; direction: ltr; text-align: start; }
.ariana-audit__url a { color: var(--ar-ink); text-decoration: underline; text-underline-offset: 2px; }

/* ---- Site health: the two weekly performance widgets ------------------- */
/* Logical properties throughout for RTL, same as the health table below.   */

.ariana-perf__bar,
.ariana-audit__bar {
    display: flex;
    align-items: center;
    gap: .75rem;
    flex-wrap: wrap;
    margin-block-end: .75rem;
}

.ariana-perf__bar-title,
.ariana-audit__bar-title {
    font-weight: 700;
    color: var(--ar-ink);
}

.ariana-perf__bar-note,
.ariana-audit__bar-note {
    font-size: .8rem;
    color: var(--ar-ink-mute);
    flex: 1 1 auto;
}

.ariana-perf {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
    gap: 1rem;
    margin-block-end: 1.5rem;
}

.ariana-perf__card {
    background: var(--ar-surface);
    border: 1px solid var(--ar-line);
    border-radius: .75rem;
    padding: 1rem 1.15rem;
    display: flex;
    flex-direction: column;
    gap: .75rem;
}

.ariana-perf__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: .75rem;
}

.ariana-perf__title {
    margin: 0;
    font-size: .95rem;
    font-weight: 700;
    color: var(--ar-ink);
}

.ariana-perf__link {
    font-size: .8rem;
    color: var(--ar-ink-dim);
    text-decoration: none;
    white-space: nowrap;
}

.ariana-perf__link:hover { text-decoration: underline; }

.ariana-perf__head-actions {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
}

.ariana-perf__refresh {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 1.6rem;
    block-size: 1.6rem;
    padding: 0;
    border: 1px solid var(--ar-line);
    border-radius: 50%;
    background: transparent;
    color: var(--ar-ink-dim);
    cursor: pointer;
    transition: color .15s ease, border-color .15s ease, transform .15s ease;
}

.ariana-perf__refresh svg {
    inline-size: .85rem;
    block-size: .85rem;
}

.ariana-perf__refresh:hover {
    color: var(--ar-ink);
    border-color: var(--ar-ink-mute);
    transform: rotate(40deg);
}

.ariana-perf__refresh:disabled { opacity: .6; cursor: default; }

/* Queued or running: the icon itself says so. */
.ariana-perf__refresh--busy svg { animation: ariana-perf-spin 1.4s linear infinite; }

@keyframes ariana-perf-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
    .ariana-perf__refresh--busy svg { animation: none; }
    .ariana-perf__refresh:hover { transform: none; }
}

.ariana-perf__scores {
    display: flex;
    align-items: center;
    gap: 1.1rem;
    flex-wrap: wrap;
}

.ariana-perf__score {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .3rem;
}

.ariana-perf__ring {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 3.25rem;
    block-size: 3.25rem;
    border-radius: 50%;
    border: 3px solid var(--ar-line);
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--ar-ink);
}

.ariana-perf__ring--good {
    color: var(--ar-success-ink);
    border-color: color-mix(in srgb, var(--ar-success-ink) 55%, transparent);
    background: color-mix(in srgb, var(--ar-success-ink) 8%, transparent);
}

.ariana-perf__ring--meh {
    color: var(--ar-warning-ink);
    border-color: color-mix(in srgb, var(--ar-warning-ink) 55%, transparent);
    background: color-mix(in srgb, var(--ar-warning-ink) 8%, transparent);
}

.ariana-perf__ring--poor {
    color: var(--ar-danger-ink);
    border-color: color-mix(in srgb, var(--ar-danger-ink) 55%, transparent);
    background: color-mix(in srgb, var(--ar-danger-ink) 8%, transparent);
}

.ariana-perf__score-label {
    font-size: .72rem;
    font-weight: 600;
    color: var(--ar-ink-mute);
    text-transform: uppercase;
    letter-spacing: .04em;
}

.ariana-perf__metrics {
    display: flex;
    gap: 1rem;
    margin: 0;
    margin-inline-start: auto;
}

.ariana-perf__metrics div { text-align: center; }

.ariana-perf__metrics dt {
    font-size: .68rem;
    font-weight: 600;
    letter-spacing: .04em;
    color: var(--ar-ink-mute);
}

.ariana-perf__metrics dd {
    margin: .1rem 0 0;
    font-size: .85rem;
    font-weight: 600;
    color: var(--ar-ink-dim);
    font-variant-numeric: tabular-nums;
}

.ariana-perf__meta {
    margin: 0;
    font-size: .75rem;
    color: var(--ar-ink-mute);
}

.ariana-perf__empty {
    margin: 0;
    font-size: .85rem;
    line-height: 1.6;
    color: var(--ar-ink-mute);
}

.ariana-perf__error {
    margin: 0;
    font-size: .78rem;
    line-height: 1.5;
    color: var(--ar-danger-ink);
    background: color-mix(in srgb, var(--ar-danger-ink) 7%, transparent);
    border-radius: .5rem;
    padding: .45rem .6rem;
}

.ariana-health__pill {
    display: inline-flex;
    align-items: center;
    font-size: .8rem;
    font-weight: 600;
    padding: .3rem .75rem;
    border-radius: 999px;
    border: 1px solid transparent;
}

.ariana-health__pill--problem {
    color: var(--ar-danger-ink);
    background: color-mix(in srgb, var(--ar-danger-ink) 10%, transparent);
    border-color: color-mix(in srgb, var(--ar-danger-ink) 25%, transparent);
}

.ariana-health__pill--warning {
    color: var(--ar-warning-ink);
    background: color-mix(in srgb, var(--ar-warning-ink) 10%, transparent);
    border-color: color-mix(in srgb, var(--ar-warning-ink) 25%, transparent);
}

.ariana-health__pill--ok {
    color: var(--ar-success-ink);
    background: color-mix(in srgb, var(--ar-success-ink) 10%, transparent);
    border-color: color-mix(in srgb, var(--ar-success-ink) 25%, transparent);
}

.ariana-health__tablewrap {
    background: var(--ar-surface);
    border: 1px solid var(--ar-line);
    border-radius: .75rem;
    overflow: hidden;
}

.ariana-health__table {
    width: 100%;
    border-collapse: collapse;
    font-size: .875rem;
    color: var(--ar-ink);
}

.ariana-health__table thead th {
    text-align: start;
    font-size: .7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--ar-ink-mute);
    background: var(--ar-sunken);
    padding: .6rem 1rem;
    border-block-end: 1px solid var(--ar-line);
}

.ariana-health__col-status { inline-size: 8.5rem; }
.ariana-health__col-name   { inline-size: 13rem; }

.ariana-health__row > td,
.ariana-health__row > th {
    padding: .8rem 1rem;
    border-block-start: 1px solid var(--ar-line);
    vertical-align: top;
}

.ariana-health__row:first-child > td,
.ariana-health__row:first-child > th { border-block-start: 0; }

.ariana-health__name {
    text-align: start;
    font-weight: 600;
    white-space: nowrap;
}

.ariana-health__detail {
    color: var(--ar-ink-dim);
    line-height: 1.55;
    white-space: pre-line; /* detail may carry deliberate line breaks */
}

.ariana-health__badge {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    font-size: .75rem;
    font-weight: 700;
    padding: .25rem .6rem;
    border-radius: 999px;
    white-space: nowrap;
}

.ariana-health__dot {
    inline-size: .45rem;
    block-size: .45rem;
    border-radius: 999px;
    background: currentColor;
}

.ariana-health__badge--ok {
    color: var(--ar-success-ink);
    background: color-mix(in srgb, var(--ar-success-ink) 12%, transparent);
}

.ariana-health__badge--warning {
    color: var(--ar-warning-ink);
    background: color-mix(in srgb, var(--ar-warning-ink) 12%, transparent);
}

.ariana-health__badge--problem {
    color: var(--ar-danger-ink);
    background: color-mix(in srgb, var(--ar-danger-ink) 12%, transparent);
}

/* The remedy strip: visually attached to its row by the shared tint and an
   accent edge on the reading side. */
.ariana-health__fixrow > td { padding: 0; border-block-start: 0; }

.ariana-health__fix {
    margin: 0 1rem .9rem;
    padding: .75rem .9rem;
    border-radius: .5rem;
    border-inline-start: 3px solid currentColor;
}

.ariana-health__fixrow--problem .ariana-health__fix {
    color: var(--ar-danger-ink);
    background: color-mix(in srgb, var(--ar-danger-ink) 7%, transparent);
}

.ariana-health__fixrow--warning .ariana-health__fix {
    color: var(--ar-warning-ink);
    background: color-mix(in srgb, var(--ar-warning-ink) 8%, transparent);
}

.ariana-health__fix-title {
    display: block;
    font-size: .7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    margin-block-end: .35rem;
}

.ariana-health__fix-body {
    margin: 0;
    color: var(--ar-ink-dim);
    line-height: 1.6;
    white-space: pre-line; /* the numbered steps arrive as \n lines */
}

.ariana-health__code {
    margin-block-start: .6rem;
    padding: .6rem .75rem;
    border-radius: .45rem;
    background: var(--ar-sunken);
    border: 1px solid var(--ar-line);
    color: var(--ar-ink);
    font-size: .78rem;
    line-height: 1.5;
    overflow-x: auto;
    direction: ltr;        /* a shell command is LTR even on an RTL panel */
    text-align: left;
    user-select: all;      /* one click selects the whole line to copy */
}

/* Narrow screens: the table becomes stacked cards. Each row keeps its badge
   beside the check name; the detail flows underneath at full width. */
@media (max-width: 640px) {
    .ariana-health__table thead { display: none; }

    .ariana-health__row {
        display: grid;
        grid-template-columns: 1fr auto;
        gap: .15rem .75rem;
        padding: .8rem 1rem;
        border-block-start: 1px solid var(--ar-line);
    }

    .ariana-health__row:first-child { border-block-start: 0; }

    .ariana-health__row > td,
    .ariana-health__row > th {
        display: block;
        padding: 0;
        border: 0;
    }

    .ariana-health__name   { order: 1; white-space: normal; }
    .ariana-health__status { order: 2; justify-self: end; }
    .ariana-health__detail { order: 3; grid-column: 1 / -1; margin-block-start: .25rem; }

    .ariana-health__fixrow { display: block; }
    .ariana-health__fixrow > td { display: block; }
    .ariana-health__fix { margin: 0 .75rem .8rem; }

    .ariana-health__summary-actions {
        margin-inline-start: 0;
        inline-size: 100%;
    }
}

/* Labels over the health page's code blocks: which artifact is which.
   Added when "paste the line" sent five schedule stars into cPanel's
   Command field — the two blocks must announce their destination. */
.ariana-health__code-label {
    display: block;
    margin-block-start: .6rem;
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--ar-ink-mute);
}

.ariana-health__code--muted { opacity: .72; }
