/* InkCMS admin skin.
   Brand: black (#0D0D0D) primary + cyan (#00B8FF) accent.
   Typography: Montserrat (Bold primary / Medium secondary) loaded
   from Google Fonts in _AdminLayout. site.css is loaded alongside
   so live content previews render with the production look (scope your
   preview HTML inside `.site-preview`).
*/

:root {
    /* Surfaces */
    --ink-bg: #fafafa;
    --ink-surface: #ffffff;
    --ink-surface-2: #f4f4f5;

    /* Borders */
    --ink-border: #e4e4e7;
    --ink-border-strong: #d4d4d8;

    /* Text — brand primary is #0D0D0D, used as the standard text color. */
    --ink-text: #0D0D0D;
    --ink-text-muted: #52525b;
    --ink-text-faint: #a1a1aa;

    /* Inverse (sidebar) — brand black. */
    --ink-inverse-bg: #0D0D0D;
    --ink-inverse-surface: #1a1a1a;
    --ink-inverse-text: #ffffff;
    --ink-inverse-text-muted: #a3a3a3;
    --ink-inverse-border: #2a2a2a;

    /* Primary action color — solid black for high-contrast buttons.
       Used by .admin-btn--primary, primary headings, etc. */
    --ink-primary: #0D0D0D;
    --ink-primary-hover: #000000;

    /* Accent — InkCMS cyan. Use for focus rings, active states, badges,
       icon highlights, and the splash motif from the logo. White text
       on this color is borderline for WCAG AA, so prefer it as a
       surface/border/highlight color, with cyan-on-white reserved for
       icons and decorative marks. Anything that needs cyan as a "link"
       color should use --ink-accent-strong instead, which is darkened
       for legibility. */
    --ink-accent: #00B8FF;
    --ink-accent-hover: #00a3e5;
    --ink-accent-strong: #0078ad;       /* WCAG-AA on white */
    --ink-accent-tint: #e0f6ff;

    /* Backwards-compat alias for the old --ink-accent (some existing
       styles use it for buttons/links). Mapped to the new primary so
       legacy uses keep behaving like solid-black accents until each
       site is touched up. */
    /* (no separate var — call sites updated to --ink-primary directly.) */

    /* Semantic */
    --ink-warn: #92400e;
    --ink-warn-tint: #fef3c7;
    --ink-error: #991b1b;
    --ink-error-tint: #fee2e2;
    --ink-ok: #166534;
    --ink-ok-tint: #dcfce7;

    /* Staging color (warm orange) */
    --ink-stage: #c2410c;
    --ink-stage-tint: #fff7ed;

    /* Effects */
    --ink-shadow-sm: 0 1px 2px rgba(0,0,0,0.04);
    --ink-shadow-md: 0 2px 8px rgba(0,0,0,0.08);
    --ink-shadow-lg: 0 8px 24px rgba(0,0,0,0.12);
    --ink-radius: 4px;
    --ink-radius-sm: 3px;
    --ink-sidebar-w: 260px;
    --ink-sidebar-w-collapsed: 56px;
    --ink-topbar-h: 56px;

    /* Type — Montserrat is the brand font. Body uses Medium (500);
       display/headings use Bold (700). System-font fallbacks keep
       the admin readable if Google Fonts is offline. */
    --ink-font: "Montserrat", "Helvetica Neue", Arial, sans-serif;
    --ink-display: "Montserrat", "Helvetica Neue", Arial Black, sans-serif;
    --ink-mono: ui-monospace, "SF Mono", Menlo, Consolas, "Courier New", monospace;
}

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

/* Admin chrome is rendered inside <body class="admin-app ...">. site.css
   is not loaded in admin, so we get a clean slate — no need for high-
   specificity overrides. */
body.admin-app {
    margin: 0;
    background: var(--ink-bg);
    color: var(--ink-text);
    font-family: var(--ink-font);
    font-size: 14px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Generic a-tag rule — low specificity so .admin-nav__link, .admin-tab,
   .admin-stat, etc. (which are also <a>'s but with their own class color)
   take precedence naturally via the class selector. */
a { color: var(--ink-accent-strong); text-decoration: none; }
a:hover { color: var(--ink-accent); text-decoration: underline; text-underline-offset: 3px; }

h1, h2, h3, h4 {
    margin: 0 0 0.5em;
    color: var(--ink-text);
}
h1 { font-family: var(--ink-display); font-size: 2rem; font-weight: 400; letter-spacing: 0.02em; text-transform: uppercase; }
h2 { font-family: var(--ink-display); font-size: 1.4rem; font-weight: 400; letter-spacing: 0.02em; text-transform: uppercase; }
h3 { font-family: var(--ink-font); font-size: 1rem; font-weight: 700; letter-spacing: 0; text-transform: none; }
p  { margin: 0 0 1em; }

code, kbd, pre {
    font-family: var(--ink-mono);
    font-size: 0.92em;
}

/* ---------- icons ---------- */

.admin-icon {
    width: 18px;
    height: 18px;
    flex: 0 0 18px;
    color: currentColor;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    vertical-align: middle;
}

.admin-btn .admin-icon { width: 16px; height: 16px; flex-basis: 16px; }
.admin-tab .admin-icon { width: 16px; height: 16px; flex-basis: 16px; }

/* ---------- shell ---------- */

.admin-shell {
    display: grid;
    grid-template-columns: var(--ink-sidebar-w) 1fr;
    grid-template-rows: var(--ink-topbar-h) 1fr;
    grid-template-areas:
        "sidebar topbar"
        "sidebar main";
    min-height: 100vh;
    transition: grid-template-columns 0.18s ease;
}

.admin-shell.is-collapsed { grid-template-columns: var(--ink-sidebar-w-collapsed) 1fr; }

/* While the user is actively dragging the sidebar resizer, kill the grid
   transition so width tracks the cursor 1:1. JS toggles this class on
   <body>; cleared on mouseup. */
body.is-resizing-sidebar .admin-shell { transition: none; }
body.is-resizing-sidebar { cursor: col-resize; user-select: none; }

.admin-shell--anon {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: 2rem 1rem;
    background: var(--ink-bg);
}

/* ---------- sidebar ---------- */

.admin-sidebar {
    grid-area: sidebar;
    background: var(--ink-inverse-bg);
    color: var(--ink-inverse-text);
    padding: 0.75rem 0.5rem 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    position: sticky;
    top: 0;
    height: 100vh;
    border-right: 1px solid var(--ink-inverse-border);
    /* overflow visible so the floating sidebar handle can protrude */
    overflow: visible;
}

/* Floating chevron handle at the sidebar's top-right edge. Protrudes
   ~14px into the main content area so it stays visible whether the
   sidebar is expanded or collapsed. */
.admin-sidebar-handle {
    position: absolute;
    top: 18px;
    right: -14px;
    width: 28px; height: 28px;
    padding: 0;
    border-radius: 50%;
    background: var(--ink-surface);
    color: var(--ink-text);
    border: 1px solid var(--ink-border-strong);
    box-shadow: var(--ink-shadow-sm);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    z-index: 5;
    transition: background 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}
.admin-sidebar-handle:hover {
    background: var(--ink-text);
    color: #fff;
    border-color: var(--ink-text);
    box-shadow: var(--ink-shadow-md);
}
.admin-sidebar-handle__chev {
    width: 14px; height: 14px;
    transition: transform 0.18s ease;
    transform: rotate(180deg);  /* points left when sidebar is expanded */
}
.is-collapsed .admin-sidebar-handle__chev {
    transform: rotate(0deg);    /* points right when sidebar is collapsed */
}

.admin-brand {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0.9rem 1rem 1rem;
    border-bottom: 1px solid var(--ink-inverse-border);
    text-decoration: none;
    /* The dark-bg logo JPG carries a pure-black backdrop that's slightly
       deeper than the sidebar's #0D0D0D. Painting the brand band black
       gives a clean "header bar" look instead of a visible rectangle
       around the JPG. PNG/JPG seams disappear; readers see one solid
       band. */
    background: #000;
}
.admin-brand:hover,
.admin-brand:focus { text-decoration: none; }
.admin-brand:focus-visible {
    /* Visible keyboard-focus indicator. Cyan outline ≥ 3:1 contrast
       on the black brand band, satisfying WCAG SC 2.4.7 / 1.4.11. */
    outline: 2px solid var(--ink-accent);
    outline-offset: -2px;
}

.admin-brand__logo {
    display: block;
    max-width: 100%;
    width: 180px;
    height: auto;
}
.admin-brand__icon {
    display: none;       /* swapped in via .is-collapsed below */
    width: 32px;
    height: 32px;
}

.is-collapsed .admin-brand__tag,
.is-collapsed .admin-nav__link span:not(.admin-icon),
.is-collapsed .admin-nav__label,
.is-collapsed .admin-user__name,
.is-collapsed .admin-user__meta,
.is-collapsed .admin-user__level,
.is-collapsed .admin-user__logout span,
.is-collapsed .admin-tree {
    display: none;
}
.is-collapsed .admin-brand { padding: 0.7rem 0; }
.is-collapsed .admin-brand__logo { display: none; }
.is-collapsed .admin-brand__icon { display: block; }
.is-collapsed .admin-nav__link { justify-content: center; padding: 0.55rem; }
.is-collapsed .admin-user { padding-top: 0.5rem; }
.is-collapsed .admin-user__logout button { padding: 0.4rem; justify-content: center; }
.is-collapsed .admin-tree-actions { display: none; }

.admin-nav {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    flex: 0 0 auto;
}

.admin-nav__label {
    font-family: var(--ink-mono);
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.18em;
    color: var(--ink-inverse-text-muted);
    padding: 0.65rem 0.85rem 0.35rem;
}

.admin-nav__link {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.5rem 0.75rem;
    border-radius: var(--ink-radius-sm);
    color: var(--ink-inverse-text-muted);
    font-size: 0.9rem;
    font-weight: 700;
    line-height: 1.2;
    transition: background 0.1s ease, color 0.1s ease;
    white-space: nowrap;
    overflow: hidden;
}

.admin-nav__link:hover {
    background: var(--ink-inverse-surface);
    color: #fff;
    text-decoration: none;
}

.admin-nav__link.is-active {
    background: #fff;
    color: var(--ink-inverse-bg);
}

.admin-nav__divider {
    height: 1px;
    background: var(--ink-inverse-border);
    margin: 0.5rem 0.25rem;
}

/* ---- Grouped nav (collapsible sections in the Administration sidebar) ----
   Built on the native <details>/<summary> element so expand/collapse works
   without JS. The summary masquerades as a regular .admin-nav__link with
   a chevron that rotates when open. Children render in a vertically
   stacked list below, indented slightly so the hierarchy reads at a glance.
   When a sub-tree (Snapshots) lives inside a group, the same pattern
   nests recursively. */

.admin-nav__group {
    /* Reset the native triangle marker; the chevron lives in the summary. */
}
.admin-nav__group > summary {
    list-style: none;
    cursor: pointer;
    user-select: none;
}
.admin-nav__group > summary::-webkit-details-marker { display: none; }

/* The summary uses the same visual treatment as .admin-nav__link so the
   header sits flush with the link list above and below. The chevron
   rotates when the group is open. */
.admin-nav__group-toggle {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.5rem 0.75rem;
    border-radius: var(--ink-radius-sm);
    color: var(--ink-inverse-text-muted);
    font-size: 0.9rem;
    font-weight: 700;
    line-height: 1.2;
    transition: background 0.1s ease, color 0.1s ease;
    white-space: nowrap;
    overflow: hidden;
}
.admin-nav__group-toggle:hover {
    background: var(--ink-inverse-surface);
    color: #fff;
}
.admin-nav__group-toggle__chev {
    margin-left: auto;
    transition: transform 0.15s ease;
}
.admin-nav__group[open] > summary > .admin-nav__group-toggle .admin-nav__group-toggle__chev {
    transform: rotate(90deg);
}

/* When the group contains the currently-active page, soften the
   summary background so admins can see "this section holds your
   current page" without making it look as bright as the actual
   active link below. */
.admin-nav__group.has-active > summary > .admin-nav__group-toggle {
    color: #fff;
}

/* Child list nested under a group. Slight indent makes the hierarchy
   readable; the indent is enough to clear the chevron but not so much
   that very long labels wrap awkwardly. */
.admin-nav__group-items {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    padding-left: 0.85rem;
    margin: 0.1rem 0 0.25rem;
    border-left: 1px solid var(--ink-inverse-border);
    margin-left: 0.85rem;
}

/* Nested groups (e.g. Snapshots within Site Administration) get the same
   treatment, recursing one more level. */
.admin-nav__group-items .admin-nav__group-items {
    padding-left: 0.85rem;
    margin-left: 0.85rem;
}

/* When the sidebar is collapsed (icons-only mode), groups collapse to
   a single icon-only summary. Children are hidden so the icon column
   stays clean; admins expand the sidebar to access deep links. */
.is-collapsed .admin-nav__group-items { display: none; }
.is-collapsed .admin-nav__group-toggle__chev { display: none; }
.is-collapsed .admin-nav__group > summary > .admin-nav__group-toggle {
    justify-content: center;
    padding: 0.55rem;
}

.admin-sidebar__scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    /* Pull the scroll track flush to the sidebar's right edge — the parent
       has 0.5rem of horizontal padding which would otherwise leave a gap
       between the track and the inner edge of the resize handle. */
    margin-right: -0.5rem;
    padding-right: 0.5rem;
    /* Firefox + the modern standards-track scrollbar. Thin track, dark
       thumb on the dark inverse background so it reads without shouting. */
    scrollbar-width: thin;
    scrollbar-color: rgba(255,255,255,0.22) transparent;
}

/* WebKit / Blink — same look, but addressable via pseudo-elements. */
.admin-sidebar__scroll::-webkit-scrollbar {
    width: 6px;
}
.admin-sidebar__scroll::-webkit-scrollbar-track {
    background: transparent;
}
.admin-sidebar__scroll::-webkit-scrollbar-thumb {
    background: rgba(255,255,255,0.18);
    border-radius: 3px;
}
.admin-sidebar__scroll::-webkit-scrollbar-thumb:hover {
    background: rgba(255,255,255,0.32);
}

/* ---------- sidebar resize handle ---------- */
.admin-sidebar-resizer {
    position: absolute;
    top: 0;
    right: -3px;             /* straddle the border so the hit-area is generous */
    width: 6px;
    height: 100%;
    cursor: col-resize;
    z-index: 4;              /* below the chevron toggle (z-index: 5) */
    background: transparent;
    transition: background 0.12s ease;
    touch-action: none;
}
.admin-sidebar-resizer:hover,
.admin-sidebar-resizer.is-active {
    background: rgba(255,255,255,0.18);
}
.is-collapsed .admin-sidebar-resizer { display: none; }

.admin-user {
    border-top: 1px solid var(--ink-inverse-border);
    padding-top: 0.85rem;
    margin: 0 0.25rem;
    color: var(--ink-inverse-text-muted);
    font-size: 0.82rem;
    flex: 0 0 auto;
}

.admin-user__name { color: #fff; font-weight: 700; font-size: 0.88rem; }
.admin-user__meta { color: var(--ink-inverse-text-muted); font-size: 0.76rem; }
.admin-user__level {
    font-family: var(--ink-mono);
    font-size: 0.66rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink-inverse-text-muted);
    margin-top: 0.2rem;
    margin-bottom: 0.6rem;
}
.admin-user__logout { margin: 0; }

/* ---------- topbar ---------- */

.admin-topbar {
    grid-area: topbar;
    display: flex;
    align-items: stretch;
    gap: 0.5rem;
    padding: 0 1rem;
    background: var(--ink-surface);
    border-bottom: 1px solid var(--ink-border);
    position: sticky;
    top: 0;
    z-index: 10;
    min-height: var(--ink-topbar-h);
}

.admin-tabs {
    display: flex;
    align-items: stretch;
    gap: 0;
    flex: 1;
    min-width: 0;
    overflow-x: auto;
}

.admin-tab {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0 0.95rem;
    color: var(--ink-text-muted);
    font-weight: 700;
    font-size: 0.88rem;
    line-height: 1;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-bottom: 2px solid transparent;
    transition: color 0.1s ease, border-color 0.1s ease;
    text-decoration: none;
    white-space: nowrap;
}

.admin-tab:hover { color: var(--ink-text); text-decoration: none; }
.admin-tab.is-active {
    color: var(--ink-text);
    border-bottom-color: var(--ink-text);
}

.admin-topbar__actions {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    flex: 0 0 auto;
}

.admin-topbar__actions .admin-btn { white-space: nowrap; }

/* Version chip — tiny, on the right edge of the topbar. Clickable for
   admins (links to the Version detail view); read-only for non-admins. */
.admin-version-chip {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    padding: 0.25rem 0.55rem;
    border: 1px solid var(--ink-border);
    border-radius: 999px;
    background: var(--ink-surface-2);
    color: var(--ink-text-muted);
    font-size: 0.72rem;
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
}
a.admin-version-chip:hover {
    background: var(--ink-surface);
    color: var(--ink-text);
    border-color: var(--ink-border-strong);
    text-decoration: none;
}
.admin-version-chip__label {
    font-family: var(--ink-mono);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-size: 0.65rem;
}
.admin-version-chip__ver {
    font-family: var(--ink-mono);
    font-weight: 600;
    color: var(--ink-text);
}

/* ---------- main ---------- */

.admin-main {
    grid-area: main;
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.admin-content {
    padding: 1.5rem;
    max-width: 1200px;
    width: 100%;
}

.admin-content__head {
    margin: -0.25rem 0 1.25rem;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.admin-content__head h1 { margin: 0; }
.admin-content__head .admin-muted { margin: 0; }

/* ---------- mobile toggle ---------- */

.admin-mobile-toggle {
    display: none;
    position: fixed;
    top: 0.6rem;
    left: 0.6rem;
    width: 38px; height: 38px;
    background: var(--ink-surface);
    border: 1px solid var(--ink-border-strong);
    border-radius: var(--ink-radius-sm);
    box-shadow: var(--ink-shadow-sm);
    cursor: pointer;
    z-index: 30;
    padding: 0;
}

.admin-mobile-toggle span {
    display: block;
    width: 18px; height: 1.5px;
    margin: 4.5px auto;
    background: var(--ink-text);
    border-radius: 1px;
}

/* ---------- cards / forms ---------- */

.admin-stack { display: flex; flex-direction: column; gap: 1.25rem; }

.admin-card {
    background: var(--ink-surface);
    border: 1px solid var(--ink-border);
    border-radius: var(--ink-radius);
    box-shadow: var(--ink-shadow-sm);
    padding: 1.5rem;
}

.admin-card--auth { width: 100%; max-width: 400px; margin: 0 auto; }
.admin-card--placeholder { border-style: dashed; border-color: var(--ink-border-strong); }

/* ---- 2FA lockdown overlay -----------------------------------------
   Applied to <body> when the user is on a 2FA challenge / enrollment
   page so the underlying admin shell can't be read over the user's
   shoulder. The shell renders normally (sharp); the ::after overlay
   sits over it with backdrop-filter: blur, and the 2FA card sits
   above the overlay with its own z-index. backdrop-filter is widely
   supported (Chrome/Edge/Safari/Firefox 103+); browsers without
   support degrade to the solid dark wash, which is still effective.
*/
body.is-2fa-locked::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 9000;
    background: rgba(15, 23, 42, 0.55);
    backdrop-filter: blur(14px) saturate(0.85);
    -webkit-backdrop-filter: blur(14px) saturate(0.85);
    pointer-events: none;
}
.admin-card--2fa {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 9100;
    width: calc(100vw - 32px);
    max-width: 480px;
    max-height: calc(100vh - 32px);
    overflow-y: auto;
    box-shadow: 0 24px 64px rgba(15, 23, 42, 0.45);
    /* Override the auth card's `margin: 0 auto` since we're absolute. */
    margin: 0;
}

/* QR-code frame for TOTP enrollment. The wrapper sizes itself; the
   service injects a viewBox into the SVG so width:100% scales it
   proportionally. !important defeats the SVG's own width/height
   attributes (browsers treat those as CSS-equivalent). */
.ink-qr-frame {
    aspect-ratio: 1 / 1;
}
.ink-qr-frame > svg {
    display: block;
    width: 100% !important;
    height: 100% !important;
}

.admin-card__head { margin-bottom: 1.25rem; }
.admin-card__head h1 { font-size: 1.7rem; margin-bottom: 0.15rem; }
.admin-card__head h3 { margin-bottom: 0.1rem; }
.admin-card__head p { margin: 0; color: var(--ink-text-muted); font-size: 0.88rem; }

.admin-form { display: flex; flex-direction: column; gap: 1.6rem; }

.admin-field { display: flex; flex-direction: column; gap: 0.4rem; padding-top: 0.4rem; }
.admin-field__label {
    font-family: var(--ink-mono);
    font-size: 0.7rem;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-text-muted);
    margin-top: 0.15rem;
}
/* Inside grids the form gap is already covered by grid `gap` — undo the
   admin-field padding-top so fields don't double-stack vertical space. */
.admin-grid > .admin-field { padding-top: 0; }
.admin-field__hint { font-size: 0.78rem; color: var(--ink-text-faint); }

.admin-input,
.admin-select,
.admin-textarea {
    width: 100%;
    padding: 0.55rem 0.75rem;
    border: 1px solid var(--ink-border-strong);
    border-radius: var(--ink-radius-sm);
    background: var(--ink-surface);
    color: var(--ink-text);
    font: inherit;
    font-family: var(--ink-font);
    transition: border-color 0.1s ease, box-shadow 0.1s ease;
}

.admin-input:focus,
.admin-select:focus,
.admin-textarea:focus {
    outline: none;
    /* Focus indicator. Border uses --ink-accent-strong so the
       contrast against a white input ≈ 5.3:1 (WCAG SC 1.4.11 requires
       3:1 minimum for UI components). The soft cyan halo on top adds
       brand color without relying on it for the contrast itself. */
    border-color: var(--ink-accent-strong);
    box-shadow: 0 0 0 3px rgba(0, 184, 255, 0.28);
}

.admin-textarea {
    resize: vertical;
    min-height: 140px;
    font-family: var(--ink-mono);
    font-size: 0.88rem;
    line-height: 1.5;
}

/* ---------- buttons ---------- */

.admin-btn {
    appearance: none;
    -webkit-appearance: none;
    border: 1px solid transparent;
    border-radius: var(--ink-radius-sm);
    padding: 0.5rem 0.85rem;
    font-family: var(--ink-font);
    font-size: 0.85rem;
    font-weight: 700;
    cursor: pointer;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    transition: background 0.1s ease, border-color 0.1s ease, color 0.1s ease;
    text-decoration: none;
}

.admin-btn--primary {
    background: var(--ink-primary);
    color: #fff;
    border-color: var(--ink-primary);
}
.admin-btn--primary:hover { background: var(--ink-primary-hover); border-color: var(--ink-primary-hover); text-decoration: none; }

.admin-btn--ghost {
    background: var(--ink-surface);
    color: var(--ink-text);
    border-color: var(--ink-border-strong);
}
.admin-btn--ghost:hover { background: var(--ink-surface-2); border-color: var(--ink-text); text-decoration: none; }

.admin-btn--stage {
    background: var(--ink-stage-tint);
    color: var(--ink-stage);
    border-color: var(--ink-stage);
}
.admin-btn--stage:hover { background: var(--ink-stage); color: #fff; text-decoration: none; }

/* Ghost button with a danger-tinted *text* — keeps the visual weight of
   the rest of the toolbar (white surface, neutral border) but signals
   that the action is destructive. Used by "Delete Page" in the page
   editor. */
.admin-btn--ghost.admin-btn--danger-text { color: #b91c1c; }
.admin-btn--ghost.admin-btn--danger-text:hover { color: #7f1d1d; }

.admin-btn--danger {
    background: #dc2626;
    color: #fff;
    border-color: #dc2626;
}
.admin-btn--danger:hover { background: #b91c1c; border-color: #b91c1c; color: #fff; text-decoration: none; }

.admin-btn--block { width: 100%; }
.admin-btn--sm    { padding: 0.4rem 0.65rem; font-size: 0.78rem; }
.admin-btn--icon  { /* gap already on .admin-btn */ }

.admin-user .admin-btn--ghost {
    background: transparent;
    color: var(--ink-inverse-text-muted);
    border-color: var(--ink-inverse-border);
    width: 100%;
}
.admin-user .admin-btn--ghost:hover {
    background: var(--ink-inverse-surface);
    color: #fff;
    border-color: var(--ink-inverse-surface);
}

/* ---------- alerts ---------- */

.admin-alert {
    padding: 0.65rem 0.85rem;
    border-radius: var(--ink-radius-sm);
    border: 1px solid transparent;
    font-size: 0.88rem;
    line-height: 1.5;
}
.admin-alert--error { background: var(--ink-error-tint); color: var(--ink-error); border-color: rgba(153,27,27,0.18); }
.admin-alert--warn  { background: var(--ink-warn-tint);  color: var(--ink-warn);  border-color: rgba(146,64,14,0.18); }
.admin-alert--ok    { background: var(--ink-ok-tint);    color: var(--ink-ok);    border-color: rgba(22,101,52,0.18); }

/* ---------- grid + stats ---------- */

.admin-grid { display: grid; gap: 1rem; }
.admin-grid--stats {
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}

.admin-stat {
    background: var(--ink-surface);
    border: 1px solid var(--ink-border);
    border-radius: var(--ink-radius);
    padding: 1.1rem 1.2rem;
    box-shadow: var(--ink-shadow-sm);
    display: block;
    color: inherit;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
    text-decoration: none;
}
.admin-stat:hover {
    text-decoration: none;
    box-shadow: var(--ink-shadow-md);
    border-color: var(--ink-text);
}

.admin-stat__num {
    font-family: var(--ink-display);
    font-size: 2.4rem;
    font-weight: 400;
    letter-spacing: 0.01em;
    color: var(--ink-text);
    line-height: 1;
}
.admin-stat__label {
    color: var(--ink-text-muted);
    font-family: var(--ink-mono);
    font-size: 0.7rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    margin-top: 0.4rem;
}

/* ---------- tags ---------- */

.admin-tags { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.admin-tag {
    background: var(--ink-surface-2);
    color: var(--ink-text);
    border: 1px solid var(--ink-border);
    border-radius: 999px;
    padding: 0.2rem 0.65rem;
    font-family: var(--ink-mono);
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 0.04em;
}

.admin-muted { color: var(--ink-text-muted); font-size: 0.86rem; }

/* ---------- content tree (sidebar) ---------- */

.admin-tree-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 0.65rem 0.4rem;
    color: var(--ink-inverse-text-muted);
}
.admin-tree-header h4 {
    margin: 0;
    font-family: var(--ink-mono);
    font-size: 0.65rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    font-weight: 600;
    color: inherit;
}

.admin-tree {
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: 0.86rem;
}

.admin-tree ul {
    list-style: none;
    margin: 0;
    padding: 0 0 0 0.85rem;
    border-left: 1px dashed var(--ink-inverse-border);
}

.admin-tree__item {
    margin: 0;
}

.admin-tree__row {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.32rem 0.5rem;
    border-radius: var(--ink-radius-sm);
    color: var(--ink-inverse-text-muted);
    cursor: grab;
    user-select: none;
}
.admin-tree__row:hover {
    background: var(--ink-inverse-surface);
    color: #fff;
}
.admin-tree__row.is-active {
    color: #fff;
    background: var(--ink-inverse-surface);
    font-weight: 700;
}

.admin-tree__row.is-dragging { opacity: 0.4; cursor: grabbing; }
.admin-tree__row.is-drop-target { background: rgba(255,255,255,0.08); outline: 1px dashed var(--ink-inverse-text-muted); }

/* "+ Add page here" affordance — muted, non-grabbable, visually
   distinct from real menu items so the eye doesn't read it as
   content. Lives at the bottom of each menu level in the tree. */
.admin-tree__row--add {
    opacity: 0.62;
    font-style: italic;
    cursor: pointer;
}
.admin-tree__row--add:hover {
    opacity: 1;
    background: rgba(255,255,255,0.06);
}
.admin-tree__item--add .admin-tree__chevron { visibility: hidden; }

/* Chevron — the visual icon is 14×14, but the hit area is 28×28 so
   admins don't keep missing and triggering the row's drag-or-navigate
   action instead. Outer span is the click surface; inner svg is the
   visual. The svg has pointer-events:none so every click lands on the
   span — predictable behavior for the click handler. */
.admin-tree__chevron {
    width: 28px; height: 28px; flex: 0 0 28px;
    margin-left: -7px;          /* preserve the row's leading edge */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    opacity: 0.7;
    border-radius: 4px;
    user-select: none;
}
.admin-tree__chevron:hover { background: rgba(255,255,255,0.08); opacity: 1; }
.admin-tree__chevron-icon {
    width: 14px; height: 14px;
    transition: transform 0.12s ease;
    pointer-events: none;
}
.admin-tree__item.is-open > .admin-tree__row .admin-tree__chevron-icon {
    transform: rotate(90deg);
}
.admin-tree__chevron--spacer { visibility: hidden; pointer-events: none; }

.admin-tree__icon {
    width: 14px; height: 14px; flex: 0 0 14px;
    color: currentColor; stroke: currentColor; fill: none; stroke-width: 1.7;
}

.admin-tree__label {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.admin-tree__badge {
    font-family: var(--ink-mono);
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--ink-inverse-text-muted);
    flex: 0 0 auto;
}

/* Color the staging badge so pending pages stand out in the sidebar. */
.admin-tree__badge.is-staging {
    color: var(--ink-stage, #c2410c);
    background: rgba(194, 65, 12, 0.18);
    border-radius: 3px;
    padding: 0.05rem 0.35rem;
}
.admin-tree__badge.is-inactive { opacity: 0.7; }

.admin-tree__item > ul {
    display: none;
}
.admin-tree__item.is-open > ul {
    display: block;
    /* Cap nested-list height so a type bucket with 100+ pages (News,
       Announcements, etc.) doesn't push the sidebar to the moon.
       overscroll-behavior: contain prevents the wheel from spilling out
       to the page once the inner scroll bottoms out. */
    max-height: 420px;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Firefox custom scrollbar */
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.25) transparent;
}
/* WebKit/Chromium custom scrollbar — slim, accent-tinted, fades in. */
.admin-tree__item.is-open > ul::-webkit-scrollbar {
    width: 8px;
}
.admin-tree__item.is-open > ul::-webkit-scrollbar-track {
    background: transparent;
}
.admin-tree__item.is-open > ul::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.18);
    border-radius: 4px;
    border: 2px solid transparent;
    background-clip: content-box;
}
.admin-tree__item.is-open > ul::-webkit-scrollbar-thumb:hover {
    background: var(--ink-accent, #00b8ff);
    background-clip: content-box;
    border: 2px solid transparent;
}

.admin-tree-loading,
.admin-tree-empty {
    padding: 0.6rem 0.85rem;
    color: var(--ink-inverse-text-muted);
    font-size: 0.82rem;
    font-style: italic;
}

.admin-tree-actions {
    display: none;
    padding: 0.5rem 0.5rem 0;
    margin-top: 0.5rem;
    border-top: 1px solid var(--ink-inverse-border);
}
.admin-tree-actions.is-dirty { display: block; }
.admin-tree-actions button {
    width: 100%;
}

/* ---------- staging banner (rendered on public site when preview cookie set) ---------- */

.ink-staging-pill {
    position: fixed;
    top: 14px;
    right: 14px;
    z-index: 9999;
    background: var(--ink-stage, #c2410c);
    color: #fff;
    border: 2px solid #fff;
    border-radius: 999px;
    padding: 0.5rem 0.95rem 0.5rem 0.7rem;
    font: 700 12px/1 Arial, Helvetica, sans-serif;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    box-shadow: 0 4px 12px rgba(0,0,0,0.18);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    cursor: pointer;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.ink-staging-pill:hover {
    text-decoration: none;
    color: #fff;
    transform: translateY(-1px);
    box-shadow: 0 6px 16px rgba(0,0,0,0.22);
}
.ink-staging-pill svg {
    width: 14px; height: 14px;
    fill: none; stroke: currentColor; stroke-width: 2;
}

/* ---------- tables ---------- */

.admin-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.88rem;
}
.admin-table thead th {
    text-align: left;
    padding: 0.7rem 1rem;
    border-bottom: 1px solid var(--ink-border);
    color: var(--ink-text-muted);
    font-family: var(--ink-mono);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    background: var(--ink-surface-2);
}
.admin-table tbody td {
    padding: 0.7rem 1rem;
    border-bottom: 1px solid var(--ink-border);
    vertical-align: middle;
}
.admin-table tbody tr:last-child td { border-bottom: none; }
.admin-table tbody tr:hover { background: var(--ink-surface-2); }
.admin-table code {
    font-family: var(--ink-mono);
    font-size: 0.82rem;
    color: var(--ink-text-muted);
}
.admin-table__actions { text-align: right; white-space: nowrap; }
.admin-table__actions .admin-btn { margin-left: 0.25rem; }

.admin-table--compact tbody td { padding: 0.45rem 0.7rem; font-size: 0.82rem; }
.admin-table--compact thead th { padding: 0.5rem 0.7rem; }

/* ---------- license page-usage banner ----------
   Renders at the top of admin-main when the operator is near/past their
   tier's page limit. Four variants escalate visual urgency from a calm
   amber (Approaching) to a hard red (HardBlock). Hidden entirely for
   Healthy and Unlimited states. */
.admin-usage-banner {
    display: flex;
    gap: 0.85rem;
    align-items: center;
    padding: 0.7rem 1.1rem;
    border-bottom: 1px solid var(--ink-border);
    font-size: 0.88rem;
    line-height: 1.4;
}
.admin-usage-banner__icon {
    flex: 0 0 1.6rem;
    height: 1.6rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--ink-mono);
    font-weight: 700;
    font-size: 0.85rem;
}
.admin-usage-banner__body { flex: 1 1 auto; }
.admin-usage-banner__body strong { margin-right: 0.25rem; }
.admin-usage-banner__cta {
    flex: 0 0 auto;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}
.admin-usage-banner__cta:hover { text-decoration: underline; }

.admin-usage-banner.is-approaching {
    background: #fffbeb;        /* amber-50 */
    color: #78350f;             /* amber-900 */
    border-bottom-color: #fde68a;
}
.admin-usage-banner.is-approaching .admin-usage-banner__icon { background: #fef3c7; color: #92400e; }
.admin-usage-banner.is-approaching .admin-usage-banner__cta { color: #b45309; }

.admin-usage-banner.is-at-limit {
    background: #fff7ed;        /* orange-50 */
    color: #7c2d12;             /* orange-900 */
    border-bottom-color: #fed7aa;
}
.admin-usage-banner.is-at-limit .admin-usage-banner__icon { background: #ffedd5; color: #9a3412; }
.admin-usage-banner.is-at-limit .admin-usage-banner__cta { color: #c2410c; }

.admin-usage-banner.is-soft-buffer {
    background: #fef2f2;        /* red-50 */
    color: #7f1d1d;             /* red-900 */
    border-bottom-color: #fecaca;
}
.admin-usage-banner.is-soft-buffer .admin-usage-banner__icon { background: #fee2e2; color: #991b1b; }
.admin-usage-banner.is-soft-buffer .admin-usage-banner__cta { color: #b91c1c; }

.admin-usage-banner.is-hard-block {
    background: #b91c1c;        /* red-700 */
    color: #fff;
    border-bottom-color: #7f1d1d;
}
.admin-usage-banner.is-hard-block .admin-usage-banner__icon { background: rgba(255,255,255,0.18); color: #fff; }
.admin-usage-banner.is-hard-block .admin-usage-banner__cta { color: #fff; text-decoration: underline; }

/* Definition list grid used by version / info views. Each row is a
   <div> wrapper around a <dt>/<dd> pair so the grid columns align. */
.admin-defs {
    margin: 0;
    display: grid;
    grid-template-columns: minmax(180px, 200px) 1fr;
    row-gap: 0.6rem;
    column-gap: 1.25rem;
    align-items: baseline;
}
.admin-defs > div { display: contents; }
.admin-defs dt {
    font-family: var(--ink-mono);
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--ink-text-muted);
    margin: 0;
}
.admin-defs dd { margin: 0; }

/* Row variant for staged pages the current admin can't publish — checkbox
   stays disabled, the row reads as inactive but the title link still works
   so they can still open the page to review/edit. */
.admin-table tbody tr.is-no-publish td { color: var(--ink-text-muted); opacity: 0.6; }
.admin-table tbody tr.is-no-publish input[type="checkbox"] { cursor: not-allowed; }

.admin-mono { font-family: var(--ink-mono); }

.admin-tag--ok  { background: var(--ink-ok-tint);    color: var(--ink-ok);    border-color: rgba(22,101,52,0.2); }
.admin-tag--err { background: var(--ink-error-tint); color: var(--ink-error); border-color: rgba(153,27,27,0.2); }

/* Adjust content head so action button sits at the right of the title block */
.admin-content__head { gap: 1.5rem; }
.admin-content__head > div { flex: 1; min-width: 0; }

details summary { cursor: pointer; }
details summary::-webkit-details-marker { color: var(--ink-text-faint); }

/* ---------- page editor tabs ---------- */

.page-tabs {
    display: flex;
    gap: 0;
    border-bottom: 1px solid var(--ink-border);
    margin-bottom: 1.25rem;
    overflow-x: auto;
}

.page-tab {
    display: inline-flex;
    align-items: center;
    padding: 0.65rem 1rem;
    color: var(--ink-text-muted);
    font-weight: 700;
    font-size: 0.82rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    border-bottom: 2px solid transparent;
    transition: color 0.1s ease, border-color 0.1s ease;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
}
.page-tab:hover { color: var(--ink-text); text-decoration: none; }
.page-tab.is-active { color: var(--ink-text); border-bottom-color: var(--ink-text); }

.page-panel { display: none; }
.page-panel.is-active { display: block; }
.page-panel > .admin-card + .admin-card { margin-top: 1rem; }

.page-save-bar {
    position: sticky;
    bottom: 0;
    background: var(--ink-surface);
    border-top: 1px solid var(--ink-border);
    /* Right padding is intentionally generous: the .ink-ai-fab floats
       fixed at right:24px (56px wide) and would otherwise sit on top of
       the rightmost button in this bar (Delete / Duplicate). 6rem ≈ 96px
       clears the 80px FAB occupy-zone plus a 16px breathing gap.
       Left padding stays at 1rem — nothing floats over the left side. */
    padding: 0.85rem 6rem 0.85rem 1rem;
    margin: 1.5rem -1.5rem -1.5rem;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    box-shadow: 0 -2px 8px rgba(0,0,0,0.04);
    z-index: 5;
}

/* Icon-only collapsed buttons inside the save bar. Each button shows
   just the icon by default; on hover / keyboard focus the label slides
   out to the right of the icon, animating both width and opacity. Screen
   readers still announce the (hidden) <span> text + the title attribute
   so this is accessible without JS. Scoped to .page-save-bar so other
   .admin-btn instances across the admin chrome stay text-labeled. */
.page-save-bar .admin-btn {
    gap: 0;
    overflow: hidden;
    /* The button width grows because the inner <span> grows; the
       padding+border transitions ride along for a smooth feel. */
    transition: background 0.1s ease,
                border-color 0.1s ease,
                color 0.1s ease,
                padding 220ms cubic-bezier(0.4, 0, 0.2, 1);
}
.page-save-bar .admin-btn > span {
    display: inline-block;
    overflow: hidden;
    white-space: nowrap;
    max-width: 0;
    opacity: 0;
    margin-left: 0;
    /* Mouseleave path — collapse immediately (no delay) so leaving the
       button doesn't stall the snap-back. max-width transition fakes the
       "grow to natural width" effect; 240px is more than enough for any
       current label. */
    transition: max-width 220ms cubic-bezier(0.4, 0, 0.2, 1),
                opacity 180ms ease,
                margin-left 220ms cubic-bezier(0.4, 0, 0.2, 1);
}
.page-save-bar .admin-btn:hover > span,
.page-save-bar .admin-btn:focus-visible > span,
.page-save-bar .admin-btn:focus-within > span {
    max-width: 240px;
    opacity: 1;
    margin-left: 0.5rem;
    /* Hover/focus path — delay BEFORE expanding. Lets users hover over
       an icon and click it without waiting for the slide animation to
       fire (or even start). 1000ms is long enough that a deliberate
       click happens well before the label slides out, short enough
       that lingering reveals it. opacity is offset by another 40ms so
       the text appears just after the slide has begun. */
    transition: max-width 220ms cubic-bezier(0.4, 0, 0.2, 1) 1000ms,
                opacity 180ms ease 1040ms,
                margin-left 220ms cubic-bezier(0.4, 0, 0.2, 1) 1000ms;
}
/* Reduced-motion users get the icon-only state without animation —
   labels still appear on hover, just instantly. */
@media (prefers-reduced-motion: reduce) {
    .page-save-bar .admin-btn,
    .page-save-bar .admin-btn > span {
        transition: none;
    }
}

/* ---------- .website wrapper inside the editor ----------
   Hook for Phase 2 when we load site.css inside an iframe and project
   live styles here. Today it's structural only. */
.cms .website { /* reserved */ }

/* ---------- CKEditor 5 sizing ---------- */

/* Make the inline editable area tall and user-resizable. CKEditor's
   actual content sits inside .ck-editor__editable_inline — give it a
   generous min-height and let the user drag the bottom edge. */
.ck.ck-editor__editable_inline {
    min-height: 360px;
    max-height: 80vh;
    resize: vertical;
    overflow: auto;
}

/* The Main Body editor gets even more room — body is the page's primary
   editing surface. */
.cms textarea[name="Body"] + .ck.ck-editor__main > .ck-editor__editable_inline,
.cms .admin-form > .admin-card > .website textarea[name="Body"] + .ck-editor__editable_inline {
    min-height: 600px;
}

/* Place a visible resize-grip hint on the bottom-right corner. */
.ck.ck-editor__editable_inline { background-image: linear-gradient(135deg, transparent 0 calc(100% - 12px), rgba(0,0,0,0.1) calc(100% - 12px) calc(100% - 11px), transparent calc(100% - 11px) calc(100% - 7px), rgba(0,0,0,0.1) calc(100% - 7px) calc(100% - 6px), transparent calc(100% - 6px)); background-position: bottom right; background-repeat: no-repeat; }

/* ---------- toast notification ---------- */

.admin-toast {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: 1000;
    background: var(--ink-ok);
    color: #fff;
    padding: 0.75rem 1.1rem;
    border-radius: var(--ink-radius-sm);
    font-weight: 600;
    font-size: 0.9rem;
    box-shadow: var(--ink-shadow-lg);
    display: flex;
    align-items: center;
    gap: 0.5rem;
    max-width: 360px;
    animation: ink-toast-in 0.2s ease-out;
}
.admin-toast--err { background: var(--ink-error); }
.admin-toast--stage { background: var(--ink-stage); }
.admin-toast.is-leaving {
    animation: ink-toast-out 0.35s ease-in forwards;
}
@keyframes ink-toast-in {
    from { transform: translateY(-12px); opacity: 0; }
    to   { transform: translateY(0); opacity: 1; }
}
@keyframes ink-toast-out {
    from { transform: translateY(0); opacity: 1; }
    to   { transform: translateY(-12px); opacity: 0; }
}

/* ---------- floating AI button + panel ---------- */

.admin-ai-fab {
    position: fixed;
    bottom: 1.5rem;
    right: 1.5rem;
    width: 52px; height: 52px;
    border-radius: 50%;
    background: var(--ink-text);
    color: #fff;
    border: none;
    cursor: pointer;
    box-shadow: var(--ink-shadow-md);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    z-index: 50;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.admin-ai-fab:hover {
    transform: translateY(-2px);
    box-shadow: var(--ink-shadow-lg);
}

.admin-ai-panel {
    position: fixed;
    bottom: 5.5rem;
    right: 1.5rem;
    width: 360px;
    max-width: calc(100vw - 3rem);
    max-height: calc(100vh - 8rem);
    background: var(--ink-surface);
    border: 1px solid var(--ink-border-strong);
    border-radius: var(--ink-radius);
    box-shadow: var(--ink-shadow-lg);
    z-index: 50;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
.admin-ai-panel[hidden] { display: none; }
.admin-ai-panel header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.65rem 0.85rem;
    background: var(--ink-inverse-bg);
    color: #fff;
    font-family: var(--ink-font);
    font-weight: 700;
}
.admin-ai-panel__close {
    background: transparent;
    color: inherit;
    border: none;
    font-size: 1.4rem;
    cursor: pointer;
    line-height: 1;
    padding: 0 0.25rem;
}
.admin-ai-panel__body {
    padding: 1rem;
    overflow-y: auto;
    font-size: 0.88rem;
}
.admin-ai-panel__body ul { padding-left: 1.2rem; margin: 0.4rem 0 0.8rem; }

/* ---------- site preview scope ---------- */

.site-preview {
    background: #fff;
    padding: 1.25rem;
    border: 1px solid var(--ink-border);
    border-radius: var(--ink-radius);
    overflow: hidden;
}

/* ---------- responsive ---------- */

@media (max-width: 880px) {
    .admin-shell {
        grid-template-columns: 1fr;
        grid-template-areas:
            "topbar"
            "main";
    }
    .admin-shell.is-collapsed { grid-template-columns: 1fr; }

    .admin-sidebar {
        position: fixed;
        inset: 0 auto 0 0;
        width: 80%;
        max-width: 280px;
        z-index: 25;
        transform: translateX(-105%);
        transition: transform 0.2s ease;
        box-shadow: var(--ink-shadow-md);
        grid-area: unset;
    }
    body.admin-nav-open .admin-sidebar { transform: translateX(0); }
    .admin-mobile-toggle { display: block; }
    .admin-topbar { padding-left: 3.75rem; }
    .admin-content { padding: 1rem; }
    .admin-sidebar-handle { display: none; }
    .admin-tabs { gap: 0; }
    .admin-tab { padding: 0 0.6rem; font-size: 0.78rem; }
    .admin-tab span:not(.admin-icon) { display: none; }
}

/* ---- Media Library grid ----------------------------------------
   .media-grid    — responsive auto-fill tile layout
   .media-tile    — anchor that wraps the thumbnail + meta block
   .media-tile__thumb__<kind> — kind-specific tinted background for
   non-image previews (generic icon sits on top via inline SVG). */
.media-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 12px;
    margin-bottom: 2rem;
}
.media-tile {
    display: flex;
    flex-direction: column;
    background: #fff;
    border: 1px solid var(--ink-border);
    border-radius: 8px;
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    transition: border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
}
.media-tile:hover {
    border-color: var(--ink-accent);
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.06);
    transform: translateY(-1px);
    text-decoration: none;
}
.media-tile:focus-visible {
    outline: 2px solid var(--ink-accent-strong);
    outline-offset: 2px;
}
.media-tile__thumb {
    aspect-ratio: 5 / 4;
    background: #f4f4f5;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    color: #71717a;
}
.media-tile__thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
/* Per-kind tints so admins can scan the grid by type at a glance. */
.media-tile__thumb--document { background: #fef3c7; color: #b45309; }
.media-tile__thumb--audio    { background: #ede9fe; color: #6d28d9; }
.media-tile__thumb--video    { background: #dbeafe; color: #1d4ed8; }

/* Child-presets toggle — small icon button on each menu-membership row
   (page editor Menus tab). Native title gives the "Child Presets" hover
   label; --set tints it when presets are configured. */
.menu-presets-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    flex: 0 0 auto;
    padding: 0;
    border: 1px solid var(--ink-border);
    border-radius: 6px;
    background: #fff;
    color: #64748b;
    cursor: pointer;
    transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.menu-presets-toggle:hover {
    background: var(--ink-accent, #00b8ff);
    border-color: var(--ink-accent, #00b8ff);
    color: #fff;
}
.menu-presets-toggle:focus-visible {
    outline: 2px solid var(--ink-accent-strong, #0078ad);
    outline-offset: 2px;
}
.menu-presets-toggle[aria-expanded="true"] {
    background: #eff6ff;
    border-color: var(--ink-accent-strong, #0078ad);
    color: var(--ink-accent-strong, #0078ad);
}
/* Tinted (with a small corner dot) when this row has presets set. */
.menu-presets-toggle--set {
    position: relative;
    border-color: var(--ink-accent-strong, #0078ad);
    color: var(--ink-accent-strong, #0078ad);
}
.menu-presets-toggle--set::after {
    content: "";
    position: absolute;
    top: -3px;
    right: -3px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--ink-accent-strong, #0078ad);
    border: 1.5px solid #fff;
}

.media-tile__body { padding: 0.65rem 0.75rem; }
.media-tile__title {
    font-size: 0.92rem;
    font-weight: 600;
    line-height: 1.3;
    margin: 0 0 0.3rem;
    color: var(--ink-text);
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.media-tile__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    font-size: 0.74rem;
    color: var(--ink-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.media-tile__kind {
    font-weight: 700;
    color: var(--ink-accent-strong);
}
.media-tile__usage {
    margin-left: auto;
    color: var(--ink-accent-strong);
    font-weight: 600;
}
.media-tile__usage--none {
    color: var(--ink-text-faint);
    font-weight: 400;
}

/* ---------- media library: upload zone + review queue ---------- */

.media-upload-zone {
    margin: 0 0 1.5rem;
    border: 2px dashed var(--ink-border-strong);
    border-radius: var(--ink-radius);
    background: var(--ink-surface);
    opacity: 0;
    transform: translateY(-6px);
    transition: opacity 0.18s ease, transform 0.18s ease, border-color 0.15s ease, background 0.15s ease;
}
.media-upload-zone[hidden] { display: none; }
.media-upload-zone.is-open { opacity: 1; transform: none; }
.media-upload-zone__inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
    text-align: center;
    padding: 2rem 1.5rem;
    color: var(--ink-text-muted);
}
.media-upload-zone__inner h2 {
    font-size: 1.05rem;
    margin: 0.4rem 0 0;
    color: var(--ink-text);
}
.media-upload-zone__inner p { margin: 0; max-width: 36rem; }
.media-upload-zone__inner svg { color: var(--ink-accent-strong); }
.media-upload-zone__inner .admin-btn + .admin-btn { margin-left: 0.5rem; }

/* Page-wide drop affordance — when a file is dragging over the document,
   the upload zone glows so the admin knows where to drop. The visual is
   restrained to the zone itself rather than veiling the page so the grid
   below stays readable. */
body.is-media-drop-target .media-upload-zone {
    border-color: var(--ink-accent-strong);
    background: var(--ink-accent-tint);
}

/* --- Queue container ----------------------------------------------- */

.media-queue {
    margin: 0 0 1.5rem;
    padding: 1rem 1.25rem 1.25rem;
    background: var(--ink-stage-tint);
    border: 1px solid #fed7aa;
    border-radius: var(--ink-radius);
}
.media-queue[hidden] { display: none; }
.media-queue__head {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas:
        "title  action"
        "desc   action";
    align-items: start;
    gap: 0.2rem 1rem;
    margin-bottom: 1rem;
}
.media-queue__head h2 {
    grid-area: title;
    margin: 0;
    font-size: 1.05rem;
    color: var(--ink-stage);
}
.media-queue__head p {
    grid-area: desc;
    margin: 0;
    font-size: 0.85rem;
    color: var(--ink-text-muted);
    max-width: 64ch;
}
.media-queue__head .admin-btn { grid-area: action; align-self: start; }
.media-queue__cards { display: flex; flex-direction: column; gap: 0.85rem; }

/* --- Card shell ----------------------------------------------------- */

.media-queue-card {
    background: var(--ink-surface);
    border: 1px solid var(--ink-border);
    border-radius: var(--ink-radius);
    padding: 0.85rem 1rem;
    box-shadow: var(--ink-shadow-sm);
}
.media-queue-card--uploading { border-color: var(--ink-border-strong); }
.media-queue-card--review    { border-color: var(--ink-accent); }
.media-queue-card--done      { border-color: var(--ink-ok); background: var(--ink-ok-tint); }
.media-queue-card--failed    { border-color: #fca5a5; background: #fef2f2; }

.media-queue-card__head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 0.75rem;
}
.media-queue-card__name {
    font-weight: 600;
    color: var(--ink-text);
    word-break: break-all;
}
.media-queue-card__name code {
    font-family: var(--ink-mono);
    font-size: 0.85rem;
    font-weight: 500;
    background: var(--ink-surface-2);
    padding: 0.1rem 0.35rem;
    border-radius: var(--ink-radius-sm);
}
.media-queue-card__status {
    font-size: 0.74rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ink-text-muted);
    white-space: nowrap;
}
.media-queue-card__status--err { color: var(--ink-error); }
.media-queue-card__status--ok  { color: var(--ink-ok); }

/* Indeterminate upload bar — pure CSS, looped. */
.media-queue-card__progress {
    margin-top: 0.6rem;
    height: 4px;
    background: var(--ink-surface-2);
    border-radius: 2px;
    overflow: hidden;
}
.media-queue-card__bar {
    height: 100%;
    width: 30%;
    background: var(--ink-accent-strong);
    border-radius: 2px;
    animation: ink-upload-bar 1.4s ease-in-out infinite;
}
@keyframes ink-upload-bar {
    0%   { transform: translateX(-100%); }
    50%  { transform: translateX(180%); }
    100% { transform: translateX(380%); }
}

.media-queue-card__error {
    margin-top: 0.5rem;
    padding: 0.6rem 0.75rem;
    background: #fef2f2;
    border: 1px solid #fca5a5;
    border-radius: var(--ink-radius-sm);
    color: var(--ink-error);
    font-size: 0.85rem;
}
.media-queue-card--failed > .admin-btn { margin-top: 0.6rem; }

/* --- Review state: preview + form ---------------------------------- */

.media-queue-card__cols {
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: 1rem;
}
@media (max-width: 720px) {
    .media-queue-card__cols { grid-template-columns: 1fr; }
}
.media-queue-card__preview {
    aspect-ratio: 5 / 4;
    background: var(--ink-surface-2);
    border-radius: var(--ink-radius-sm);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--ink-text-faint);
}
.media-queue-card__preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.media-queue-card__preview--document { background: #fef3c7; color: #b45309; }
.media-queue-card__preview--audio    { background: #ede9fe; color: #6d28d9; }
.media-queue-card__preview--video    { background: #dbeafe; color: #1d4ed8; }

.media-queue-card__form { display: flex; flex-direction: column; gap: 0.6rem; }
.media-queue-card__form .admin-field { padding-top: 0; }
.media-queue-card__form .admin-textarea { min-height: 56px; font-family: var(--ink-font); font-size: 0.9rem; }

.media-queue-card__suggestion {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.25rem;
    padding: 0.2rem 0.55rem;
    background: var(--ink-accent-tint);
    color: var(--ink-accent-strong);
    border-radius: 999px;
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 0.02em;
}
.media-queue-card__suggestion.is-fallback {
    background: var(--ink-warn-tint);
    color: var(--ink-warn);
}

.media-queue-card__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.5rem;
}
.media-queue-card__msg { font-size: 0.85rem; color: var(--ink-text-muted); }
.media-queue-card__msg.is-err { color: var(--ink-error); }
.media-queue-card__msg.is-ok  { color: var(--ink-ok); }

/* ---------- media library: swap-file status ---------- */
.media-swap-status {
    font-size: 0.85rem;
    color: var(--ink-text-muted);
}
.media-swap-status.is-ok  { color: var(--ink-ok); }
.media-swap-status.is-err { color: var(--ink-error); }

/* ---------- media library: pager ---------- */

.media-pager {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem;
    margin: 1.25rem 0 0.5rem;
    justify-content: center;
}
.media-pager__btn,
.media-pager__page {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2rem;
    padding: 0.35rem 0.65rem;
    border: 1px solid var(--ink-border);
    border-radius: var(--ink-radius-sm);
    color: var(--ink-text);
    background: var(--ink-surface);
    font-size: 0.85rem;
    font-weight: 600;
    text-decoration: none;
    line-height: 1;
}
.media-pager__btn:hover,
.media-pager__page:hover {
    border-color: var(--ink-accent-strong);
    color: var(--ink-accent-strong);
    text-decoration: none;
}
.media-pager__page.is-current {
    background: var(--ink-primary);
    color: #fff;
    border-color: var(--ink-primary);
}
.media-pager__btn.is-disabled {
    color: var(--ink-text-faint);
    pointer-events: none;
    border-color: var(--ink-border);
    background: var(--ink-surface-2);
}
.media-pager__gap {
    color: var(--ink-text-faint);
    padding: 0 0.25rem;
    user-select: none;
}

/* Inline AI spinner used inside the suggestion pill. */
.ai-spinner {
    display: inline-block;
    width: 0.85em;
    height: 0.85em;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: ink-spin 0.7s linear infinite;
    vertical-align: -0.15em;
}
@keyframes ink-spin {
    to { transform: rotate(360deg); }
}

/* ---------- demo-seed banner ---------- */
/* Shown across every admin page when the install is running on shipped
   FMR demo content. Visible until the admin acknowledges or wipes via
   /administer/administration/clear-demo. */
.demo-seed-banner {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.65rem 1rem;
    margin: 0 0 1.25rem;
    background: var(--ink-warn-tint);
    border: 1px solid rgba(146, 64, 14, 0.25);
    border-left: 4px solid var(--ink-warn);
    border-radius: var(--ink-radius);
    color: var(--ink-warn);
    font-size: 0.9rem;
    line-height: 1.45;
}
.demo-seed-banner__icon {
    flex: 0 0 auto;
    color: var(--ink-warn);
    margin-top: 0.1rem;
}
.demo-seed-banner__body {
    flex: 1 1 auto;
    color: #6b3a08;  /* slightly darker than --ink-warn for readability */
}
.demo-seed-banner__body strong {
    color: var(--ink-warn);
    font-weight: 700;
    margin-right: 0.3rem;
}
.demo-seed-banner__cta {
    flex: 0 0 auto;
    background: var(--ink-warn);
    color: #fff;
    padding: 0.4rem 0.75rem;
    border-radius: var(--ink-radius-sm);
    font-size: 0.82rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    text-decoration: none;
    white-space: nowrap;
}
.demo-seed-banner__cta:hover {
    background: #78350f;
    color: #fff;
    text-decoration: none;
}
