/* ===== admin-shell.css — OKAMI CMS admin-only chrome (V.104 CSS split) =====
   Split out of the former app.css. Everything in this file only ever
   appears on an /admin/* route (or the unauthenticated login screen) —
   sidebar/topbar, admin list/form design system, the UI Kit style-guide
   page's own styles, and the Dynamic/Global Builder EDITOR widgets
   (query-config, item-list, menu-items row editor). Load after tokens.css. */

.auth-shell {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px;
}

/* V.065 — login screen rebuild (DECISIONS.md #084), Universal UI/UX Kit
   V12 visual language: a real branded split layout instead of one bare
   centered card. Left panel is decorative brand identity (gradient built
   from the existing --accent/--accent-dark tokens — so a Settings > Theme
   custom color change reflects here too, no separate login-only palette);
   right panel holds the actual form in the same card language the rest
   of the admin already uses. Collapses to a single column on narrow
   screens (brand panel becomes a compact header band, not two full
   screens stacked) — this is the login screen's own responsive rule
   since it renders before app.css's later frontend-only breakpoints and
   isn't inside `.frontend-body`. */
.login-body { margin: 0; min-height: 100vh; overflow-x: hidden; }
.login-shell { min-height: 100vh; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.login-brand {
  display: grid; grid-template-rows: 1fr auto; gap: 24px; padding: 48px;
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-dark) 100%);
  color: #fff; position: relative; overflow: hidden;
}
/* V.322 — a settings-chosen background image, with a brand-gradient overlay so
   the text stays legible on any photo. Layered: gradient first, image second. */
.login-brand--image {
  background-image: linear-gradient(135deg, color-mix(in srgb, var(--accent) 82%, transparent) 0%, color-mix(in srgb, var(--accent-dark) 86%, transparent) 100%), var(--login-bg);
  background-size: cover, cover; background-position: center, center; background-repeat: no-repeat, no-repeat;
}
.login-brand__inner { align-self: center; }
/* Pinned brand footer: CMS name · version, and the credit line. */
.login-brand__foot {
  position: relative; display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px 20px; flex-wrap: wrap; padding-top: 18px; border-top: 1px solid rgba(255,255,255,.18);
  font-size: var(--fs-12_5);
}
.login-brand__site { font-weight: 800; letter-spacing: .01em; }
.login-brand__ver { font-weight: 600; opacity: .7; }
.login-brand__credit { opacity: .8; font-weight: 600; color: #fff; text-decoration: none; }
a.login-brand__credit:hover { opacity: 1; text-decoration: underline; }
.login-brand::before {
  content: ""; position: absolute; inset: -20% -20% auto auto; width: 60%; aspect-ratio: 1;
  background: rgba(255, 255, 255, .08); border-radius: 50%;
}
.login-brand::after {
  content: ""; position: absolute; inset: auto auto -25% -15%; width: 50%; aspect-ratio: 1;
  background: rgba(255, 255, 255, .06); border-radius: 50%;
}
.login-brand__inner { position: relative; max-width: 360px; }
.login-brand__mark {
  width: 56px; height: 56px; border-radius: var(--rs); background: rgba(255, 255, 255, .16);
  display: flex; align-items: center; justify-content: center; font-size: var(--fs-26); font-weight: 900;
  margin-bottom: 24px; border: 1px solid rgba(255, 255, 255, .25);
}
.login-brand__name { font-size: var(--fs-28); font-weight: 900; margin-bottom: 10px; letter-spacing: -.01em; }
/* V.317 — clamp the tagline so a longer-than-expected PHASE_LABEL can never
   blow out the brand panel height (it did in V.046-048; belt-and-braces here). */
.login-brand__tagline { font-size: var(--fs-14); line-height: 1.55; opacity: .88; margin: 0 0 28px; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
.login-brand__version { font-size: var(--fs-11); text-transform: uppercase; letter-spacing: .1em; opacity: .6; font-weight: 700; }
/* V.317 — password label + Forgot-password link on one row. */
.login-field-row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.login-forgot { font-size: var(--fs-12_5); color: var(--accent, #c0392b); text-decoration: none; font-weight: 600; }
.login-forgot:hover { text-decoration: underline; }
.login-form-side { display: flex; align-items: center; justify-content: center; padding: 24px; background: var(--bg); }
.login-card { width: 100%; max-width: 380px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--shadow); padding: 36px 32px; }
.login-card__lede { margin: 4px 0 22px; font-size: var(--fs-13); }
.login-locale-row { margin-top: 18px; display: flex; gap: 8px; justify-content: center; }
@media (max-width: 780px) {
  .login-shell { grid-template-columns: 1fr; }
  .login-brand { padding: 32px 24px; min-height: 180px; }
  .login-brand__inner { max-width: none; }
  .login-brand__tagline { margin-bottom: 0; }
  .login-brand { min-height: 200px; gap: 16px; }
  .login-brand--image { min-height: 240px; }
  .login-brand__foot { padding-top: 14px; }
}
/* V.317 — never let long brand copy push the panel wider than the screen. */
.login-brand__inner, .login-brand__name, .login-brand__tagline { overflow-wrap: anywhere; max-width: 100%; }

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow);
  padding: 32px;
  width: 100%;
  max-width: 380px;
}
.panel.wide { max-width: none; }
.panel.pad { padding: 22px; }
.mt { margin-top: 20px; }
.mb { margin-bottom: 20px; }

.eyebrow {
  font-size: var(--fs-10);
  text-transform: uppercase;
  letter-spacing: .18em;
  color: var(--accent);
  font-weight: 900;
}

h1 { font-size: var(--fs-24); margin: 8px 0 4px; }
.muted { color: var(--muted); }

.field { margin: 16px 0; }
.field label { display: block; font-size: var(--fs-11); font-weight: 800; margin-bottom: 5px; }
/* Phase 16 — a11y fix: group headings over a set of checkboxes/radios/
   static text (not a single associated control) render as `<span>`, not
   `<label>`, so screen readers don't announce them as if they targeted one
   specific input that isn't actually there. Same visual style as a real
   field label, just correct semantics underneath. */
.field-legend { display: block; font-size: var(--fs-11); font-weight: 800; margin-bottom: 5px; }
.field input:not([type="checkbox"]):not([type="radio"]) {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: var(--rs);
  padding: 10px 12px;
  font: inherit;
  background: #fff;
  transition: border-color .12s ease, box-shadow .12s ease;
}
/* Phase C (DECISIONS.md #112) — every admin form control shared one plain
   `border-color` on focus at best, most had no focus treatment at all
   (`.field input`/`.field select`/`.field textarea`, the permalink slug
   field, taxonomy filter/chip inputs). A form this size needs a real,
   consistent focus ring so keyboard users (and everyone else) can always
   tell which field is active — same accent + soft-shadow language the
   Dashboard's `.app-search input:focus` already established, just applied
   everywhere a form control appears. `:focus-visible` (not `:focus`) so a
   plain mouse click into a text field doesn't ring it. */
.field input:not([type="checkbox"]):not([type="radio"]):focus-visible,
.field select:focus-visible,
.field textarea:focus-visible,
.permalink-row input[type="text"]:focus-visible,
.tax-filter:focus-visible,
.repeater-row input:not([type="checkbox"]):not([type="radio"]):focus-visible,
.repeater-row select:focus-visible,
.repeater-row textarea:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--soft);
}

.notice { border-radius: var(--rs); padding: 10px 12px; font-size: var(--fs-12); margin-bottom: 12px; border: 1px solid var(--line); }
.notice.error { border-color: #edb3b3; background: #fff5f5; color: var(--danger); }
.notice.success { border-color: #b8e3d2; background: #f3fbf7; color: var(--success); }
.notice.warning { border-color: #ecd09e; background: #fffaf0; color: var(--warning); }
.notice.info { border-color: #b8d4ec; background: #f2f8fd; color: #2b6cb0; }

/* Pill-toggle choice inputs — OKAMI UI Kit V5's .pill/.pill.active pattern
   (see the kit's own :root tokens/`.pill.active` rule) applied to Attribute
   select/multiselect values on Product/Service forms in place of plain
   checkbox/radio rows (ad-hoc addition, DECISIONS.md #029). The real
   <input type="checkbox"/radio"> stays in the DOM (visually hidden) so the
   form still works with zero JS and assistive tech still sees a real
   control — only the label is styled as the clickable pill. */
.pill-toggle-group { display: flex; flex-wrap: wrap; gap: 7px; }
.pill-toggle { position: absolute; opacity: 0; width: 1px; height: 1px; overflow: hidden; }
.pill-toggle-label {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--line); background: #f0f3f5; border-radius: 999px;
  padding: 7px 13px; font-size: var(--fs-12); color: var(--muted); cursor: pointer;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
  user-select: none;
}
.pill-toggle-label:hover { border-color: #cbd8ff; }
.pill-toggle:checked + .pill-toggle-label {
  background: var(--soft); border-color: #cbd8ff; color: var(--accent); font-weight: 800;
}
.pill-toggle:focus-visible + .pill-toggle-label { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ===== Admin Shell (Phase 02) ===== */
.app-shell { display: grid; grid-template-columns: 250px 1fr; min-height: 100vh; transition: grid-template-columns .15s; }
.app-sidebar {
  background: var(--dark);
  color: #cfd6dd;
  padding: 20px 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.app-sidebar .brand { color: #fff; font-weight: 950; letter-spacing: .02em; padding: 6px 8px 20px; display: flex; align-items: center; gap: 10px; }
.app-sidebar .brand .version-tag { display: block; color: #7c8794; font-weight: 700; font-size: var(--fs-10); letter-spacing: .04em; text-transform: none; }
/* V.113 — brand logo/mark (Phase A shell revamp, reference #3's "small
   logo/workspace switcher at top"). Real site logo (Settings > Header's
   `site_logo_media_id`) when one is set; a plain initial-in-a-tinted-
   square otherwise. Never a second logo system — same Media Library
   record the frontend header already renders (App\Support\PageTemplates::
   logoUrl()). */
.brand-logo { width: 34px; height: 34px; border-radius: 10px; object-fit: cover; flex-shrink: 0; background: #fff; }
.brand-mark {
  width: 34px; height: 34px; border-radius: 10px; flex-shrink: 0; background: var(--accent); color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: var(--fs-16); font-weight: 900;
}
.brand-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.brand-text .brand-name { font-size: var(--fs-14); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nav-group { font-size: var(--fs-10); text-transform: uppercase; letter-spacing: .12em; color: #7c8794; padding: 16px 10px 7px; white-space: nowrap; font-weight: 800; }
.nav-link {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  border-radius: var(--rs);
  font-size: var(--fs-13);
  font-weight: 650;
  color: #cfd6dd;
  transition: background .12s ease, color .12s ease;
}
.nav-link:hover { background: rgba(255,255,255,.07); color: #fff; }
.nav-link.active { background: var(--accent); color: #fff; box-shadow: 0 6px 16px -6px rgba(40,95,242,.55); }
.nav-link.disabled { color: #566270; cursor: default; }
.nav-link.disabled:hover { background: transparent; color: #566270; }
.nav-link.disabled.active { background: rgba(40,95,242,.35); color: #dce2e7; }
.nav-link .nav-icon { width: 15px; height: 15px; flex-shrink: 0; }
.nav-link .nav-link-label { flex: 1; white-space: nowrap; }
.nav-link .soon { font-size: var(--fs-9); text-transform: uppercase; letter-spacing: .08em; background: rgba(255,255,255,.08); border-radius: 999px; padding: 2px 6px; margin-left: auto; }
/* V.113 — icon-in-a-soft-tinted-circle treatment (reference #2/#3's
   "colored icon-in-a-soft-circle on the left"), reusing the existing
   --tint-a/b/c/d pairs (DECISIONS.md #104) rather than inventing a new
   palette. One fixed tint per nav GROUP (not random per item) so related
   items read as one visual family; `data-tint` is assigned once, by
   group, in layouts/admin.php. */
.nav-icon-wrap {
  width: 26px; height: 26px; border-radius: 8px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  transition: background .12s ease, color .12s ease;
}
.nav-icon-wrap[data-tint="a"] { background: var(--tint-a-bg); color: var(--tint-a-ink); }
.nav-icon-wrap[data-tint="b"] { background: var(--tint-b-bg); color: var(--tint-b-ink); }
.nav-icon-wrap[data-tint="c"] { background: var(--tint-c-bg); color: var(--tint-c-ink); }
.nav-icon-wrap[data-tint="d"] { background: var(--tint-d-bg); color: var(--tint-d-ink); }
.nav-link.active .nav-icon-wrap { background: rgba(255,255,255,.22); color: #fff; }
.nav-link.disabled .nav-icon-wrap { opacity: .45; }

/* V.046 — icon-only rail while a Visual Builder screen is open (see
   layouts/admin.php's $isBuilderScreen). The real admin nav stays fully
   navigable (every link/permission/route is unchanged) — only the visual
   presentation collapses, so the owner keeps full admin access while a
   builder canvas gets the horizontal room the mockup called for. */
.app-shell--builder-rail { grid-template-columns: 64px 1fr; }
.app-shell--builder-rail .app-sidebar { padding: 16px 10px; align-items: center; }
.app-shell--builder-rail .app-sidebar .brand { padding: 0 0 14px; justify-content: center; }
.app-shell--builder-rail .app-sidebar .brand-text,
.app-shell--builder-rail .nav-group,
.app-shell--builder-rail .nav-link-label,
.app-shell--builder-rail .nav-link .soon { display: none; }
.app-shell--builder-rail .nav-link { justify-content: center; padding: 10px; width: 40px; }

/* V.103 (DECISIONS.md #111) — mobile sidebar toggle button + backdrop.
   Hidden by default (desktop always shows the real sidebar); the
   @media (max-width:900px) block below reveals it, since that's the same
   breakpoint that already hides .app-sidebar outright. */
.app-sidebar-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--line);
  border-radius: var(--rs);
  background: var(--surface);
  color: var(--ink);
  font-size: 17px; /* decorative hamburger glyph, not reading text — not part of the type scale */
  flex-shrink: 0;
  cursor: pointer;
}
.app-sidebar-toggle:hover { background: var(--soft); }
.app-sidebar-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(10,14,20,.45);
  z-index: 40;
}

/* min-width: 0 overrides the grid item's default min-width:auto — without
   it, .app-main (a grid track of .app-shell) refuses to shrink below the
   min-content width of whatever's inside it (e.g. a wide table), which
   was silently forcing the entire admin shell wider than the viewport on
   mobile regardless of any overflow-x:auto set further down the tree
   (DECISIONS.md #111). */
.app-main { display: flex; flex-direction: column; min-height: 100vh; min-width: 0; }
.app-top {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  padding: 16px 28px;
  display: flex;
  align-items: center;
  gap: 16px;
}
.app-search { flex: 1; max-width: 420px; position: relative; }
/* V.113 — rounded pill search bar (reference #1's "clean rounded search
   bar"). Same functional widget/JS as before, only the visual shape
   changed: full-pill radius, room for the leading magnifier glyph. */
.app-search input {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 10px 14px 10px 36px;
  font: inherit;
  font-size: var(--fs-13);
  background: var(--bg);
}
.app-search input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--soft); background: var(--surface); }
.app-search::before {
  content: ""; position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  width: 12px; height: 12px; border: 2px solid var(--muted); border-radius: 50%;
  box-shadow: 4px 4px 0 -2.5px var(--muted); opacity: .7; pointer-events: none;
}
.app-search-results {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--rs);
  box-shadow: var(--shadow);
  max-height: 320px;
  overflow: auto;
  display: none;
  z-index: 50;
}
.app-search-results.open { display: block; }
.app-search-results a { display: block; padding: 10px 12px; border-bottom: 1px solid var(--line); font-size: var(--fs-13); }
.app-search-results a:last-child { border-bottom: 0; }
.app-search-results a:hover { background: var(--soft); }
.app-search-empty { padding: 10px 12px; font-size: var(--fs-12); color: var(--muted); }

.app-content { padding: 28px; max-width: 1100px; width: 100%; margin: 0 auto; }
/* .breadcrumb moved to tokens.css (V.104 hotfix) — it's used by BOTH the
   admin layout (this file) AND the public frontend (App\Support\PageParts::
   breadcrumb()), so it must live in the one file both surfaces load, not
   here. Was silently unstyled on every frontend page after the V.104 CSS
   split until this fix — admin-shell.css never loads on public pages. */
.page-head { display: flex; justify-content: space-between; align-items: end; gap: 20px; margin-bottom: 20px; }
.page-head h1 { font-size: var(--fs-22); margin: 4px 0 0; }
/* V.113 — page title + subtitle row (reference #3's "page title + subtitle").
   Optional — a `.page-head` with no `.page-head__subtitle` renders exactly
   as before on every screen that hasn't adopted it yet. */
.page-head__subtitle { color: var(--muted); font-size: var(--fs-13); margin: 4px 0 0; }
/* A long two-line description in the left column (e.g. Products' own) was
   squeezing the right-hand action button's flex basis down to the point
   its own label wrapped onto two lines ("+ New" / "Product") — the button
   must never shrink or wrap, and its own left sibling must be allowed to
   shrink instead (owner-reported real layout break, screenshot). */
/* V.113 fix — `:last-child` alone also matches a `.page-head` with only ONE
   child (e.g. Dashboard's title block, which has no right-hand action
   button) — that lone child was getting flex-shrink:0 meant only for a
   real second/action column, so it could never shrink below its own
   max-content width and silently forced page-level horizontal overflow
   on narrow viewports (confirmed via scrollWidth on the Dashboard's own
   long version/phase-label badge text). `:not(:only-child)` scopes the
   "never shrink" rule back to its intended two-column case. */
.page-head > *:last-child:not(:only-child) { flex-shrink: 0; }
.page-head > *:first-child { min-width: 0; }

.stat-grid { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 14px; margin-bottom: 24px; }
.stat-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--shadow); padding: 20px; position: relative; transition: box-shadow .15s ease, transform .15s ease; }
.stat-card:hover { box-shadow: 0 22px 44px -16px rgba(15,22,29,.22); transform: translateY(-1px); }
.stat-card .label { font-size: var(--fs-11); text-transform: uppercase; letter-spacing: .1em; color: var(--muted); font-weight: 800; padding-right: 34px; }
.stat-card .value { font-size: var(--fs-28); font-weight: 900; margin-top: 6px; }
/* V.113 — Dashboard KPI card anatomy (reference #3: label, big number, a
   small context line, small icon top-right). No fake percentage-change
   pill — `.stat-card .context` only ever renders a real, already-computed
   figure (e.g. "Last 30 days") never a fabricated trend. */
.stat-card .context { font-size: var(--fs-11_5); color: var(--muted); margin-top: 7px; }
.stat-card__icon {
  position: absolute; top: 18px; right: 18px; width: 32px; height: 32px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.stat-card__icon svg { width: 15px; height: 15px; }
.stat-card__icon[data-tint="a"] { background: var(--tint-a-bg); color: var(--tint-a-ink); }
.stat-card__icon[data-tint="b"] { background: var(--tint-b-bg); color: var(--tint-b-ink); }
.stat-card__icon[data-tint="c"] { background: var(--tint-c-bg); color: var(--tint-c-ink); }
.stat-card__icon[data-tint="d"] { background: var(--tint-d-bg); color: var(--tint-d-ink); }

.table { width: 100%; border-collapse: collapse; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; box-shadow: var(--shadow); }
.table th, .table td { padding: 13px 16px; border-bottom: 1px solid var(--line); text-align: left; font-size: var(--fs-13); }
.table th { font-size: var(--fs-11); text-transform: uppercase; letter-spacing: .06em; color: var(--muted); background: #fafbfc; font-weight: 800; }
.table tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: #fafbfc; }
.table .row-actions { display: flex; gap: 6px; justify-content: flex-end; }
/* V.113 — data-table "avatar + name" first-column anatomy (reference #3),
   opt-in via `.table-avatar` on the cell — no existing `.table` markup
   anywhere else changes shape since this is purely additive. */
.table-avatar { display: flex; align-items: center; gap: 10px; }
.table-avatar__mark {
  width: 30px; height: 30px; border-radius: 50%; background: var(--soft); color: var(--accent);
  display: flex; align-items: center; justify-content: center; font-size: var(--fs-11_5); font-weight: 800; flex-shrink: 0;
}
/* Phase B — same `.table-avatar` anatomy, but for rows whose real thumbnail
   is a rectangular cover image (Products/Services/Blog/Pages) rather than a
   circular initial. `--img` swaps the mark to a soft-cornered image frame;
   an `<img>` inside it fills it via object-fit, a missing cover just shows
   the empty tinted frame (no broken-image icon). */
.table-avatar__mark--img { border-radius: 8px; background: #eef1f4; overflow: hidden; }
.table-avatar__mark--img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.table-avatar__body { min-width: 0; }
.table-avatar__title { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* Phase B — mobile-safe horizontal scroll wrapper for any `.table` that
   might overflow a narrow viewport (long name/email/action columns). Applied
   consistently across every admin list/index table instead of ad hoc inline
   `style="overflow-x:auto"` (Dashboard's Recent Activity table already did
   this inline — new tables use this class instead). */
.table-scroll { overflow-x: auto; }

.bulkbar {
  display: none;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: var(--dark);
  color: #fff;
  border-radius: var(--rs);
  padding: 10px 14px;
  margin-bottom: 12px;
  font-size: var(--fs-13);
}
.bulkbar.open { display: flex; }

.form { display: grid; gap: 14px; max-width: 480px; }
/* Phase C — was 9px vertical padding vs the text input's 10px above;
   close enough to go unnoticed alone, but visible the moment a text field
   sits directly next to a select/textarea in the same `.field` stack
   (Attribute type picker, taxonomy display-style select, every WYSIWYG
   textarea). Matched to the same 10px/12px box so every control in a form
   reads as one consistent height/rhythm. */
.field select, .field textarea { width: 100%; border: 1px solid var(--line); border-radius: var(--rs); padding: 10px 12px; font: inherit; background: #fff; transition: border-color .12s ease, box-shadow .12s ease; }
.checkrow { display: flex; align-items: center; gap: 8px; font-size: var(--fs-13); padding: 6px 0; }

.empty-state { background: var(--surface); border: 1px dashed var(--line); border-radius: var(--r); padding: 48px 24px; text-align: center; color: var(--muted); }
.empty-state .eyebrow { display: block; margin-bottom: 8px; }
.empty-state h2 { font-size: var(--fs-18); color: var(--ink); margin: 0 0 8px; }

.activity-row { font-size: var(--fs-13); }
.activity-row .meta { color: var(--muted); font-size: var(--fs-11); }

/* ===== Taxonomy term tree (ad-hoc V.024 attributes/taxonomy UI upgrade —
   see DECISIONS.md #043) — replaces the old flat table with inline
   `padding-left:depth*20px` indentation with a real nested list, connector
   lines drawn via a border on each item, expand/collapse, and drag-reorder
   handles (siblings only, persisted to `sort_order` via a small AJAX
   endpoint — TaxonomyController::reorderTerms()). ===== */
.term-tree, .term-tree__children { list-style: none; margin: 0; padding: 0; }
.term-tree__children { margin-left: 26px; padding-left: 14px; border-left: 1px dashed var(--line); }
.term-tree__item { position: relative; margin: 2px 0; }
.term-tree__row {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; border-radius: var(--rs);
  border: 1px solid transparent;
}
.term-tree__row:hover { background: #fafbfc; border-color: var(--line); }
.term-tree__toggle {
  width: 18px; height: 18px; flex: 0 0 18px; border-radius: 4px; border: 1px solid var(--line);
  background: #fff; color: var(--muted); font-size: var(--fs-12); line-height: 1; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; padding: 0;
}
.term-tree__toggle--spacer { border: none; background: none; cursor: default; }
.term-tree__handle { cursor: grab; color: var(--muted); font-size: var(--fs-14); flex: 0 0 auto; user-select: none; }
.term-tree__icon { flex: 0 0 auto; width: 18px; height: 18px; color: var(--accent); }
.term-tree__icon svg { width: 100%; height: 100%; }
.term-tree__name { font-weight: 700; font-size: var(--fs-13); }
.term-tree__slug { font-size: var(--fs-11); }
.term-tree__count { padding: 3px 8px; font-size: var(--fs-10); margin-left: auto; }
.term-tree__item[draggable="true"] .term-tree__row { cursor: default; }
.term-tree__item.is-dragging .term-tree__row { opacity: .5; }

/* Icon picker grid — used on the Taxonomy term form's Icon field. */
.icon-picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 8px; max-height: 260px; overflow-y: auto; padding: 4px; border: 1px solid var(--line); border-radius: var(--rs); }
.icon-picker__option {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  border: 1px solid var(--line); background: #fff; border-radius: var(--rs);
  padding: 10px 6px; cursor: pointer; font-size: var(--fs-10); color: var(--muted); text-align: center;
}
.icon-picker__option svg { width: 20px; height: 20px; stroke: currentColor; }
.icon-picker__option:hover { border-color: #cbd8ff; }
.icon-picker__option.is-selected { border-color: var(--accent); background: var(--soft); color: var(--accent); font-weight: 700; }

/* ===== Admin index-page / form design system (ad-hoc V.025 — owner:
   "all look odd and unpresentable... dropdown missing, ajax, skeleton,
   distraction-free forms like WordPress, KPI cards, bulk actions,
   pagination, search bar missing"). Shared across every admin list/form
   screen — built once here, applied first to Products + Blog (the
   flagship pair), the rest of the admin follows the same classes. ===== */

/* --- Generic dropdown (public/assets/js/admin-dropdown.js) — backs the
   top-bar user menu, per-row Actions kebab, and any future menu. --- */
.dropdown { position: relative; display: inline-block; }
.dropdown-toggle { cursor: pointer; }
.dropdown-menu {
  display: none; position: absolute; right: 0; top: calc(100% + 6px); z-index: 60;
  min-width: 170px; background: #fff; border: 1px solid var(--line); border-radius: var(--rs);
  box-shadow: 0 8px 24px rgba(20, 25, 35, .12); padding: 6px; overflow: hidden;
}
.dropdown-menu.align-left { right: auto; left: 0; }
.dropdown.open .dropdown-menu { display: block; }
.dropdown-menu a, .dropdown-menu button {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  padding: 8px 10px; border-radius: 6px; border: none; background: none;
  font: inherit; font-size: var(--fs-13); color: var(--ink); cursor: pointer; white-space: nowrap;
}
.dropdown-menu a:hover, .dropdown-menu button:hover { background: var(--soft); color: var(--accent); }
.dropdown-menu button.danger:hover { background: #fff0f0; color: var(--danger); }
.dropdown-menu hr { border: none; border-top: 1px solid var(--line); margin: 6px 0; }
.dropdown-menu .dropdown-meta { padding: 8px 10px; font-size: var(--fs-11); color: var(--muted); }
.row-actions-kebab {
  width: 30px; height: 30px; border-radius: 6px; border: 1px solid var(--line); background: #fff;
  color: var(--muted); font-size: 16px; /* decorative kebab glyph */ line-height: 1; cursor: pointer; display: inline-flex;
  align-items: center; justify-content: center;
}
.row-actions-kebab:hover { border-color: #cbd8ff; color: var(--accent); }

/* --- Phase 17 (translation) — top-bar language switcher --- */
.app-lang-menu .dropdown-toggle {
  display: flex; align-items: center; justify-content: center; width: 36px; height: 36px;
  border: 1px solid var(--line); background: #fff; border-radius: 999px; cursor: pointer; font-size: 16px; /* decorative globe glyph */
}
.app-lang-menu .dropdown-menu button { justify-content: space-between; }

/* --- Top-bar user menu --- */
.app-user-menu .dropdown-toggle {
  display: flex; align-items: center; gap: 8px; border: 1px solid var(--line); background: #fff;
  border-radius: 999px; padding: 5px 12px 5px 5px; cursor: pointer; font: inherit; font-size: var(--fs-13); color: var(--ink);
}
.app-user-menu .avatar {
  width: 26px; height: 26px; border-radius: 50%; background: var(--accent); color: #fff;
  display: inline-flex; align-items: center; justify-content: center; font-size: var(--fs-11); font-weight: 800;
}

/* --- KPI stat cards --- */
.kpi-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 18px; }
/* V.103 (DECISIONS.md #111) — same card role as .stat-card (Dashboard)
   but was missing box-shadow entirely, reading as a flatter, older
   component even though it's used right alongside .stat-card-styled
   widgets on Roles/Taxonomies/Attributes/Media. */
.kpi-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--shadow); padding: 14px 16px; transition: box-shadow .15s ease, transform .15s ease; }
.kpi-card:hover { box-shadow: 0 22px 44px -16px rgba(15,22,29,.22); transform: translateY(-1px); }
/* Phase C (DECISIONS.md #112) — repeater rows (FAQ/Reviews here, same
   shape used by the Attribute-value chip rows and the taxonomy Add-New
   mini-form) were the roughest part of every long form: a bare 1px
   border+8px padding box with no separation from its neighbors and, for
   FAQ specifically, no visual "this is one card" affordance at all. One
   shared `.repeater-row` card look — soft tinted background (not stark
   white-on-white against the surrounding card), a touch more radius/
   padding, a hover lift matching `.stat-card`/`.kpi-card`'s existing
   hover language, and room reserved top-right for a remove control via
   `.repeater-row__remove` where a row has one. `.faq-row`/`.review-row`
   keep their own class names too — admin-wizard.js/the inline repeater
   scripts below select rows by those, unchanged — this only adds the
   shared visual layer on top. */
.repeater-row, .faq-row, .review-row {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--rs);
  background: var(--bg);
  padding: 14px 44px 14px 14px;
  margin-bottom: 10px;
  transition: box-shadow .15s ease, border-color .15s ease;
}
.repeater-row:hover, .faq-row:hover, .review-row:hover { border-color: #d7dee8; box-shadow: 0 8px 20px -14px rgba(15,22,29,.35); }
.repeater-row:last-child, .faq-row:last-child, .review-row:last-child { margin-bottom: 0; }
.repeater-row__remove {
  position: absolute;
  top: 10px;
  right: 10px;
}
/* A repeater row's OWN field stack shouldn't also inherit the page's 16px
   `.field` vertical rhythm — it already sits inside the row's 14px
   padding, so the same rule every repeater row above already applied
   inline (`style="margin:0 0 8px"` etc.) is now just the default here. */
.repeater-row .field, .faq-row .field, .review-row .field { margin: 0 0 10px; }
.repeater-row .field:last-child, .faq-row .field:last-child, .review-row .field:last-child { margin-bottom: 0; }

/* Manual attribute-kind repeater row — mirrors `.faq-row`/`.review-row`
   exactly (same card look, border, hover lift) per the owner-approved
   mockups; kept as its own class only because the JS repeater targets it
   by that name, same as .faq-row/.review-row do for theirs. */
.manual-attr-row {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--rs);
  background: var(--bg);
  padding: 14px 44px 14px 14px;
  margin-bottom: 10px;
  display: flex; gap: 10px; flex-wrap: wrap;
  transition: box-shadow .15s ease, border-color .15s ease;
}
.manual-attr-row:hover { border-color: #d7dee8; box-shadow: 0 8px 20px -14px rgba(15,22,29,.35); }
.manual-attr-row:last-child { margin-bottom: 0; }
.manual-attr-row .field { flex: 1; min-width: 160px; margin: 0; }
.manual-attr-row__remove { position: absolute; top: 10px; right: 10px; }
@media (max-width: 560px) {
  .manual-attr-row { flex-direction: column; padding-right: 14px; }
  .manual-attr-row__remove { position: static; margin-top: 6px; align-self: flex-start; }
}

/* Attributes/Specifications/Features/Applications/Industries tabs —
   owner-approved mockups ("apply these 100% same no skipping"): each of
   the 5 kind tabs is ONE card containing two stacked boxes, Engine (the
   existing Attribute-Library AJAX search-to-add UI) on top, Manual
   (one-off value repeater, this product only) below. `.mode-tag` is a
   small pill label distinguishing the two, reusing the same soft-blue
   `--soft`/`--accent` pair the rest of this admin already uses for
   "engine/library" affordances, and a new soft-orange pair (matching
   `.pill.warning`'s existing `#fff2e0`/`#b5680a`) for "manual". */
.attr-kind-tab { display: flex; flex-direction: column; gap: 16px; }
.attr-engine-box, .attr-manual-box {
  border: 1px solid var(--line); border-radius: var(--r); background: var(--surface); padding: 16px;
}
.attr-manual-box { background: #fffaf3; border-color: #f3e2c2; }
.attr-box-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 4px; }
.attr-box-head__title { font-size: var(--fs-13); font-weight: 800; color: var(--ink); }
.mode-tag {
  display: inline-flex; align-items: center; font-size: 10px; font-weight: 800; letter-spacing: .04em;
  padding: 2px 8px; border-radius: 999px; text-transform: uppercase;
}
.mode-tag.engine { background: var(--soft); color: var(--accent); }
.mode-tag.manual { background: #fff2e0; color: #b5680a; }
.attr-manual-box__hint { font-size: var(--fs-11); color: var(--muted); margin: 0 0 10px; }
.attr-engine-box [data-attr-kind-section] { margin-top: 8px; }

/* Phase C — a field-group row that lays two/three inputs out side by side
   (the Review row's Reviewer/Rating/Date trio was the one genuine risk:
   three flex children with no basis, no wrap, done as a raw inline style
   with nothing to collapse it on a 390px screen). `.form-row` replaces
   that inline `style="display:flex;gap:10px"` pattern with a class that
   collapses to a single column under 560px, matching the same breakpoint
   `.grid.g2` already collapses at. */
.form-row { display: flex; gap: 10px; }
.form-row > .field { flex: 1; min-width: 0; }
@media (max-width: 560px) {
  .form-row { flex-direction: column; gap: 0; }
}

/* Phase C — a small colored dot ahead of a sub-section heading inside a
   tab panel (Gallery/Videos/Downloads/Certificates, FAQ/Reviews, …) so a
   long single-tab form still reads as visually GROUPED sections, not one
   undifferentiated scroll — the same "grouped, distinct sections" idea
   the owner's mobile Settings reference showed, scaled down to a heading
   marker rather than a full icon-in-a-circle (no new icon assets needed;
   see DECISIONS.md #112). Reuses `.admin-edit-card h3`'s exact type
   styling so a `.section-title` inside a tab panel and an `.admin-edit-
   card h3` in a sidebar-card layout read as the same visual language. */
.section-title {
  display: flex; align-items: center; gap: 8px;
  margin: 22px 0 4px; font-size: var(--fs-13); font-weight: 800; color: var(--ink);
}
[data-media-bucket] .section-title, [data-attr-kind-section] .section-title { margin-top: 0; }
/* Gallery/Videos/Downloads/Certificates render as separate sibling
   `[data-media-bucket]` blocks with nothing marking where one ends and
   the next begins — add the same "distinct grouped section" separation
   line the reference direction called for, between buckets only (the
   first bucket needs none, matching `.section-title`'s own zeroed
   margin above). */
[data-media-bucket] + [data-media-bucket] { margin-top: 26px; padding-top: 22px; border-top: 1px solid var(--line); }
.section-title::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex: 0 0 auto;
}
.section-title + p.muted { margin-top: 0; }
/* V.341 — per-section "Display style" override header (product form). Gives the
   title + dropdown row room to breathe and a proper divider, and styles the
   select to match admin inputs. */
.attr-sec-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 0 0 16px; padding-bottom: 14px; border-bottom: 1px solid var(--line); }
.attr-sec-style { margin-left: auto; display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 700; color: var(--muted); }
.attr-sec-style__sel { appearance: none; -webkit-appearance: none; border: 1px solid var(--line); border-radius: 9px; padding: 8px 32px 8px 12px; font: inherit; font-size: 13px; font-weight: 700; color: var(--ink); background: var(--surface, #fff) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238a95a2' stroke-width='2'><path d='M6 9l6 6 6-6'/></svg>") no-repeat right 10px center; cursor: pointer; min-height: 38px; }
.attr-sec-style__sel:hover { border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); }
.attr-sec-style__sel:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent); }
.attr-sec-style__sel.is-set { border-color: var(--accent); color: var(--accent); background-color: color-mix(in srgb, var(--accent) 6%, #fff); }
.attr-sec-note { font-size: 11.5px; margin: -6px 0 14px; }
@media (max-width: 560px) { .attr-sec-style { margin-left: 0; width: 100%; } .attr-sec-style__sel { flex: 1; } }
.kpi-card .kpi-label { font-size: var(--fs-11); text-transform: uppercase; letter-spacing: .05em; color: var(--muted); font-weight: 700; }
.kpi-card .kpi-value { font-size: var(--fs-26); font-weight: 800; color: var(--ink); margin-top: 4px; line-height: 1.1; }
.kpi-card.accent .kpi-value { color: var(--accent); }
.kpi-card.success .kpi-value { color: var(--success); }
.kpi-card.muted .kpi-value { color: var(--muted); }
.kpi-card.danger .kpi-value { color: var(--danger); }

/* --- Index-page toolbar: search + filters + New button row --- */
.admin-toolbar { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 14px; flex-wrap: wrap; }
.admin-toolbar-left { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.admin-search { position: relative; }
.admin-search input {
  width: 240px; max-width: 60vw; border: 1px solid var(--line); border-radius: var(--rs);
  padding: 8px 12px 8px 30px; font: inherit; font-size: var(--fs-13); background: #fff;
}
.admin-search::before {
  content: ""; position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  width: 13px; height: 13px; border: 2px solid var(--muted); border-radius: 50%;
  box-shadow: 4px 4px 0 -2.5px var(--muted); opacity: .7;
}
.admin-filter-select {
  border: 1px solid var(--line); border-radius: var(--rs); padding: 8px 10px; font: inherit; font-size: var(--fs-13); background: #fff;
}

/* --- Bulk action bar (generalizes the existing .bulkbar to a dropdown-select shape) --- */
.bulk-select { border: 1px solid var(--line); border-radius: 6px; padding: 6px 8px; font: inherit; font-size: var(--fs-12); background: #fff; color: var(--ink); }
.table-checkbox-col { width: 34px; }

/* --- Pagination --- */
.pagination { display: flex; gap: 6px; justify-content: center; align-items: center; margin-top: 18px; flex-wrap: wrap; }
.pagination a, .pagination span.page-current, .pagination span.page-ellipsis {
  min-width: 32px; height: 32px; padding: 0 8px; border-radius: 6px; border: 1px solid var(--line);
  display: inline-flex; align-items: center; justify-content: center; font-size: var(--fs-12); color: var(--ink); background: #fff;
}
.pagination a:hover { border-color: #cbd8ff; color: var(--accent); }
.pagination span.page-current { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 800; }
.pagination span.page-ellipsis { border: none; color: var(--muted); }
.pagination-summary { text-align: center; font-size: var(--fs-12); color: var(--muted); margin-top: 8px; }

/* --- Skeleton loading state (shown in the list region while admin-list.js's AJAX fetch is in flight) --- */
.skeleton-block { background: linear-gradient(90deg, #eef1f4 25%, #f5f7f9 37%, #eef1f4 63%); background-size: 400% 100%; animation: skeleton-shimmer 1.4s ease infinite; border-radius: 4px; }
@keyframes skeleton-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
.skeleton-table .skeleton-cell { height: 14px; margin: 4px 0; }
.skeleton-table tr td { padding: 14px; }

/* --- WordPress-style distraction-free 2-column form layout --- */
.title-field input {
  width: 100%; font-size: var(--fs-22); font-weight: 800; padding: 12px 14px; border: 1px solid var(--line);
  border-radius: var(--r); margin-bottom: 16px; font-family: inherit; background: #fff;
}
/* V.064 — WordPress-style permalink/slug editor row (DECISIONS.md #083),
   shared markup contract driven by assets/js/admin-permalink.js. */
.permalink-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0 0 16px; font-size: var(--fs-13); }
.permalink-label { color: var(--muted); }
.permalink-prefix { color: var(--muted); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.permalink-row input[type="text"] { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: var(--fs-13); padding: 4px 8px; border: 1px solid var(--line); border-radius: 6px; min-width: 160px; }
.permalink-row--locked input[type="text"] { background: var(--bg); color: var(--muted); }
.permalink-row .btn-link { background: none; border: none; color: var(--accent); cursor: pointer; font-size: var(--fs-12); padding: 0; text-decoration: underline; }
.permalink-hint { flex-basis: 100%; margin: 2px 0 0; color: var(--muted); font-size: var(--fs-11); }

.postbox-layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 20px; align-items: start; }
.postbox-main { min-width: 0; }
.postbox-sidebar { display: flex; flex-direction: column; gap: 16px; position: sticky; top: 16px; }
.postbox { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.postbox-header { padding: 10px 14px; border-bottom: 1px solid var(--line); background: #fafbfc; font-weight: 800; font-size: var(--fs-12); text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.postbox-body { padding: 14px; }
.postbox-body .field:last-child { margin-bottom: 0; }
.postbox-actions { display: flex; gap: 8px; }
.postbox-actions .btn { flex: 1; justify-content: center; }
@media (max-width: 960px) {
  .postbox-layout { grid-template-columns: 1fr; }
  .postbox-sidebar { position: static; }
}

/* --- Tabs (main-column content inside a form, replacing a long stacked <h3> list) --- */
.tabs-nav { display: flex; gap: 2px; border-bottom: 1px solid var(--line); margin-bottom: 18px; flex-wrap: wrap; }
.tabs-nav button {
  padding: 10px 14px; border: none; background: none; font: inherit; font-size: var(--fs-13); font-weight: 700;
  color: var(--muted); cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tabs-nav button:hover { color: var(--ink); }
.tabs-nav button.active { color: var(--accent); border-bottom-color: var(--accent); }
.tab-panel { display: none; }
.tab-panel.active { display: block; }
.tab-panel > h3:first-child { margin-top: 0; }

/* ===== V5 Kit utilities (adopted ad-hoc, DECISIONS.md #025) =====
   Genuinely-missing pieces UI-KIT-RECONCILIATION.md flagged as safe
   "ADOPT AS NEW" — copied verbatim from the real V5 Kit source
   (OKAMI-UNIVERSAL-UI-UX-KIT-V5-FINAL-MASTER.html), not re-derived from the
   older V4-era reconciliation notes. No brand-color or token changes. */
.container { max-width: var(--container); margin: 0 auto; }

.grid { display: grid; gap: 16px; }
.grid.g2 { grid-template-columns: repeat(2, minmax(0,1fr)); }
.grid.g3 { grid-template-columns: repeat(3, minmax(0,1fr)); }
.grid.g4 { grid-template-columns: repeat(4, minmax(0,1fr)); }
.grid.g5 { grid-template-columns: repeat(5, minmax(0,1fr)); }

.skeleton {
  background: linear-gradient(90deg, #edf0f2 25%, #fafbfc 37%, #edf0f2 63%);
  background-size: 400% 100%;
  animation: sk 1.2s infinite;
  border-radius: 9px;
}
@keyframes sk { to { background-position: -400% 0; } }
.skeleton.skbig { height: 160px; }
.skeleton.skline { height: 13px; margin-top: 9px; }
.skeleton.short { width: 55%; }

@media (max-width: 900px) {
  .app-shell { grid-template-columns: 1fr; }
  .app-sidebar-toggle { display: inline-flex; }
  /* V.103 (DECISIONS.md #111) — the sidebar used to just vanish here with
     no way back in. Now it's an off-canvas panel: fixed, slid off-screen
     by default, slides in over a backdrop when .app-shell--sidebar-open
     is toggled by admin-sidebar-toggle.js. */
  .app-sidebar {
    display: flex;
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    width: 250px;
    max-width: 82vw;
    z-index: 41;
    transform: translateX(-100%);
    transition: transform .2s ease;
    overflow-y: auto;
  }
  .app-shell--sidebar-open .app-sidebar { transform: translateX(0); }
  .app-shell--sidebar-open .app-sidebar-backdrop { display: block; }
  .stat-grid { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .grid.g4, .grid.g3, .grid.g5 { grid-template-columns: repeat(2, minmax(0,1fr)); }
  /* V.103 (DECISIONS.md #111) — none of the ~19 admin `.table` list views
     (products, blog, services, inquiries, users, pages, redirects,
     activity-log, roles, taxonomies, attributes, menus, etc.) had any
     mobile handling at all — a table with 6-8 columns just overflowed the
     screen with no way to see the rest. `display:block` on the table
     itself (its thead/tbody keep their normal table-header-group/
     table-row-group display, so column alignment between header and body
     rows is unaffected) plus `overflow-x:auto` turns the table into its
     own horizontally-scrollable box — confirmed via a real Playwright
     scrollWidth/clientWidth check that this fixes it with zero page-level
     horizontal overflow, for every one of these views at once, no PHP
     template changes needed. */
  .table { display: block; width: 100%; max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .row-actions-buttons { flex-wrap: wrap; }
}

@media (max-width: 560px) {
  .grid.g2 { grid-template-columns: 1fr; }
}

/* ===== UI Kit style guide page (DECISIONS.md #025) ===== */
.kit-section { margin: 0 0 40px; }
.kit-section h2 { font-size: var(--fs-16); margin: 0 0 4px; }
.kit-section .kit-desc { margin: 0 0 14px; }
.kit-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 10px; }
.kit-swatch { display: flex; flex-direction: column; gap: 6px; width: 110px; }
.kit-swatch .chip { height: 54px; border-radius: var(--rs); border: 1px solid var(--line); }
.kit-swatch code { font-size: var(--fs-10); color: var(--muted); word-break: break-all; }
code.tag { background: var(--soft); color: var(--accent); border-radius: 6px; padding: 2px 6px; font-size: var(--fs-11); font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; }
pre.kit-code { background: var(--dark); color: #d8e0e8; border-radius: var(--rs); padding: 14px 16px; font-size: var(--fs-12); overflow-x: auto; margin: 10px 0 0; }

/* V.110 orphan cleanup — the `.query-config` settings-field sub-widget
   (Phase 10 Dynamic Builder) and its entire `.qc-*` descendant tree were
   removed here: verified zero references anywhere in resources/views,
   app/**/*.php, or assets/js/**/*.js (not just the bare `.query-config`
   wrapper the UI Kit audit flagged — none of `.qc-row`/`.qc-sublabel`/
   `.qc-section`/`.qc-filter-row`/`.qc-condition-row`/`.qc-term-list`/
   `.qc-term-checkbox` appear anywhere either, confirming this whole
   sub-widget was never wired into any real admin view). See
   `app/Support/UiKitAudit.php`'s live orphan report.
*/

/* ===== Round D — UI Kit rebuild Phase 3 (DECISIONS.md #103). The admin
   panel now follows the SAME owner-configured theme preset/custom colors
   as the frontend, per the owner's own explicit choice ("frontend jaisa
   theme follow kare") — reversing V.063's original deliberate "admin stays
   untouched" boundary. Scoped to `.app-shell[data-theme="..."]` (the admin
   root wrapper — see resources/views/layouts/admin.php), applied via the
   same `App\Support\Theme::preset()`/`::css()` FrontendController already
   used, now shared rather than admin-specific. The 3 light presets reskin
   for free (every admin component already reads --accent/--soft same as
   frontend); Dark needs the same explicit component overrides frontend
   needed, PLUS more — the admin UI has many more literal `background:#fff`
   form-control/menu-chrome rules than the frontend does. This pass covers
   every generic form control and the highest-traffic menu/chrome elements;
   any remaining literal-white spot found later is a disclosed, incremental
   gap to close in a future round, not a silent omission (see DECISIONS.md
   #103's own note — this is a first pass, not claimed to be exhaustive). */
.app-shell[data-theme="blue"] { --accent: #285ff2; --soft: #edf2ff; }
.app-shell[data-theme="emerald"] { --accent: #16855e; --soft: #eaf8f1; }
.app-shell[data-theme="amber"] { --accent: #b56b00; --soft: #fff4df; }
.app-shell[data-theme="rust"] { --accent: #b23a1e; --soft: #fbece6; }
.app-shell[data-theme="dark"] {
  --bg: #0b1015;
  --surface: #121920;
  --ink: #edf2f6;
  --muted: #9aa7b2;
  --line: #29343e;
  --accent: #6f98ff;
  --soft: #18243d;
  --shadow: 0 20px 45px -12px rgba(0, 0, 0, .38);
  /* --dark stays the sidebar's own near-black — already dark-appropriate,
     unlike frontend's --dark (a text-ink token there), so it's deliberately
     NOT overridden here. */
}
.app-shell[data-theme="dark"] input,
.app-shell[data-theme="dark"] select,
.app-shell[data-theme="dark"] textarea,
.app-shell[data-theme="dark"] .dropdown-menu,
.app-shell[data-theme="dark"] .postbox-header,
.app-shell[data-theme="dark"] .bulk-select,
.app-shell[data-theme="dark"] .row-actions-kebab,
.app-shell[data-theme="dark"] .app-lang-menu .dropdown-toggle,
.app-shell[data-theme="dark"] .app-user-menu .dropdown-toggle {
  background: var(--surface); color: var(--ink); border-color: var(--line);
}
.app-shell[data-theme="dark"] .btn.danger { background: var(--surface); }
.app-shell[data-theme="dark"] img { opacity: .92; }

/* Editor: the generic item-list widget (powers carousel/stats_bar/logo_strip/testimonials editors) */
/* =====================================================================
   Ad-hoc V.016 — Frontend Visual Refresh
   (ADHOC-V016-FRONTEND-VISUAL-REFRESH-PLAN.md). Owner picked the light
   UI-Kit direction (Decision #001's real tokens above), not the dark
   navy/gold mockup theme — every rule below builds on the existing
   --bg/--surface/--ink/--muted/--line/--accent/--soft/--dark/--r/--rs/
   --shadow tokens, no new palette introduced.
   ===================================================================== */

/* V.110 orphan cleanup — the `.il-row`/`.il-row__controls` generic
   "item-list" widget rules were removed here: verified zero references
   anywhere in resources/views, app/**/*.php, or assets/js/**/*.js. The
   comment that used to sit here also referenced a `.mi-row` sibling class
   that never existed anywhere in this file either — both never made it
   past the widget's design stage; carousel/stats_bar/logo_strip/
   testimonials editors render via a different, real implementation
   elsewhere. See `app/Support/UiKitAudit.php`'s live orphan report.
*/

/* --- Forms wizard (V.029 — owner: Products/Services forms converted into a
   step wizard, DECISIONS.md #048). Layered on top of the existing
   .postbox-layout/.tabs-nav/.tab-panel markup from V.025/026 — a
   `.wizard-form` form gets a fixed health bar above its (now sticky)
   `.tabs-nav`, numbered step buttons, and a "Review & Publish" final step
   appended by admin-wizard.js. Every step stays independently clickable
   (no forced linear order) per the confirmed scope. */
.wizard-health { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); padding: 12px 14px; margin-bottom: 14px; }
.wizard-health__row { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.wizard-health__row:last-child { margin-bottom: 0; }
.wizard-health__label { font-size: var(--fs-11); font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); width: 108px; flex: 0 0 auto; }
.wizard-health__bar { flex: 1 1 auto; height: 8px; background: #eef1f4; border-radius: 999px; overflow: hidden; }
.wizard-health__fill { height: 100%; background: var(--accent); border-radius: 999px; transition: width .2s ease; }
.wizard-health__fill.is-complete { background: #1fa971; }
.wizard-health__pct { width: 40px; flex: 0 0 auto; text-align: right; font-size: var(--fs-12); font-weight: 800; color: var(--ink); }
.wizard-health__steps { display: flex; flex-wrap: wrap; gap: 6px; }
.wizard-health__step-pct { font-size: var(--fs-10); padding: 2px 7px; border-radius: 999px; background: #f0f3f5; color: var(--muted); font-weight: 700; }
.wizard-health__step-pct.is-complete { background: var(--soft); color: var(--accent); }

.wizard-step-num {
  display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px;
  border-radius: 50%; background: #eef1f4; color: var(--muted); font-size: var(--fs-10); font-weight: 800; margin-right: 6px;
}
.wizard-form .tabs-nav button.active .wizard-step-num { background: var(--accent); color: #fff; }
.wizard-form .tabs-nav button.step-complete .wizard-step-num { background: #1fa971; color: #fff; }
.wizard-form .tabs-nav button[data-tab-target="review"] { margin-left: auto; }

.wizard-savebar { display: flex; align-items: center; gap: 10px; margin: 14px 0; padding: 10px 12px; background: var(--soft); border: 1px solid #cbd8ff; border-radius: var(--rs); }
.wizard-savebar__msg { font-size: var(--fs-12); color: var(--muted); }
.wizard-savebar__msg.is-ok { color: #1fa971; font-weight: 700; }
.wizard-savebar__msg.is-error { color: #c0392b; font-weight: 700; }

.wizard-review dl { display: grid; grid-template-columns: 220px 1fr; gap: 6px 14px; margin: 0 0 18px; }
.wizard-review dt { font-size: var(--fs-11); font-weight: 800; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); }
.wizard-review dd { margin: 0; font-size: var(--fs-13); color: var(--ink); word-break: break-word; }
.wizard-review h4 { font-size: var(--fs-12); text-transform: uppercase; letter-spacing: .04em; color: var(--muted); margin: 0 0 8px; border-bottom: 1px solid var(--line); padding-bottom: 6px; }
/* V.364 — the editable Draft/Published choice on the Review & Publish step. */
.wizard-review-status { margin: 0 0 18px; padding: 14px 16px; background: var(--soft); border: 1px solid #cbd8ff; border-radius: var(--rs); }
.wizard-review-status label { display: block; font-size: var(--fs-11); font-weight: 800; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); margin: 0 0 6px; }
.wizard-review-status select { font: inherit; font-size: var(--fs-14); font-weight: 700; padding: 9px 12px; min-width: 200px; border: 1px solid var(--line); border-radius: var(--rs); background: #fff; color: var(--ink); }
.wizard-review-status__hint { margin: 8px 0 0; font-size: var(--fs-12); color: var(--muted); }

/* V.030 — direct row-action buttons (owner: "button e nai hamburger menu e
   button do view eidt duplicate" — the kebab/hamburger dropdown menu on
   Products/Services lists is replaced with always-visible buttons). */
.row-actions-buttons { display: flex; gap: 6px; flex-wrap: nowrap; justify-content: flex-end; }

/* Phase 14 — hand-rolled CSS bar charts for the Analytics screen (Page
   Views / Leads trend), matching this project's no-external-JS-charting-
   library convention. Bars are plain divs whose height is set inline per
   data point (real percentage-of-max, computed in the view). */
.bar-chart { display: flex; align-items: flex-end; gap: 3px; height: 120px; padding: 8px 4px 0; border-bottom: 1px solid var(--line); }
.bar-chart__bar { flex: 1 1 0; background: var(--accent, #3d6bff); border-radius: 2px 2px 0 0; min-height: 1px; position: relative; }
.bar-chart__bar:hover { opacity: .75; }
.bar-chart-labels { display: flex; justify-content: space-between; font-size: var(--fs-10); color: var(--muted); margin-top: 4px; }

.row-actions-buttons form { display: inline; margin: 0; }

/* V.050 — Deploy Center: real styled checkbox for the "force" toggle
   (was a bare native checkbox), and an AJAX upload progress bar so a
   deploy shows upload % then an "Applying update…" state instead of a
   blank frozen page while the browser posts a multi-MB zip. */
.deploy-force-toggle {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: var(--fs-13);
  font-weight: 400;
  color: var(--ink);
  margin-bottom: 14px;
  cursor: pointer;
  user-select: none;
}
.deploy-force-toggle__input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.deploy-force-toggle__box {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  border-radius: 5px;
  border: 1.5px solid var(--line);
  background: var(--surface);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  transition: background .12s ease, border-color .12s ease;
}
.deploy-force-toggle__box svg { opacity: 0; transform: scale(.6); transition: opacity .12s ease, transform .12s ease; }
.deploy-force-toggle__input:checked + .deploy-force-toggle__box { background: var(--accent); border-color: var(--accent); }
.deploy-force-toggle__input:checked + .deploy-force-toggle__box svg { opacity: 1; transform: scale(1); }
.deploy-force-toggle__input:focus-visible + .deploy-force-toggle__box { outline: 2px solid var(--accent); outline-offset: 2px; }
.deploy-force-toggle:hover .deploy-force-toggle__box { border-color: var(--accent); }
.deploy-force-toggle__lb { line-height: 1.45; padding-top: 1px; }

.deploy-progress { margin-top: 14px; max-width: 420px; }
.deploy-progress__row { display: flex; justify-content: space-between; font-size: var(--fs-12); color: var(--muted); margin-bottom: 6px; }
.deploy-progress__pct { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--ink); }
.deploy-progress__track { height: 8px; border-radius: 999px; background: var(--soft); overflow: hidden; }
.deploy-progress__bar { height: 100%; border-radius: 999px; background: var(--accent); transition: width .15s ease; }
.deploy-progress__bar--indeterminate {
  width: 100% !important;
  background: linear-gradient(90deg, var(--soft) 0%, var(--accent) 50%, var(--soft) 100%);
  background-size: 200% 100%;
  animation: deployProgressSweep 1.2s ease-in-out infinite;
}
@keyframes deployProgressSweep {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .deploy-progress__bar--indeterminate { animation: none; }
}

/* V.052 — reusable "distraction-free" 2-column edit layout (owner: "2 side
   One for content one for action lke shopify worpderss"), added here to
   the Universal Kit so any edit screen can adopt it rather than each
   screen hand-rolling its own version. Content (the fields someone is
   actually here to write — name, description, body copy) lives in the
   wide `.admin-edit-main` column; everything that organizes or acts on
   that content (parent/relationships, icon/status pickers, Save/Cancel)
   lives in the narrow `.admin-edit-side` column, split into its own
   `.admin-edit-card` blocks with a soft heading each — the same "a group
   with nothing to show is omitted" spirit as the Builder's settings
   panel groups. Falls back to a single column under 900px. */
.admin-edit-layout { display: grid; grid-template-columns: 1fr 320px; gap: 22px; align-items: start; }
.admin-edit-main, .admin-edit-side { display: flex; flex-direction: column; gap: 18px; }
/* Phase C (DECISIONS.md #112) — sticky-save-bar pass. `.postbox-sidebar`
   (Products/Services/Blog/Settings/Media) already keeps Save in view via
   `position: sticky` (line ~560 above) while the main column scrolls;
   `.admin-edit-side` (Users/Roles/Attributes/Taxonomy Term/Type) never
   got the same treatment, so Save could scroll out of view on the
   longer ones (Attributes' 3-card main column, a Term with a filled-in
   Image box). Same sticky pattern, not a new fixed-bottom bar — the two
   layouts already share the "actions live in a narrow side column"
   shape, so keeping the mechanism identical between them is the more
   consistent fix. The Menu Builder's own dedicated `.sticky-cta` bottom
   bar (a different, single-column, no-sidebar layout) is untouched. */
.admin-edit-side { position: sticky; top: 16px; }
.admin-edit-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  padding: 22px; box-shadow: var(--shadow);
}
.admin-edit-card h3 {
  margin: 0 0 4px; font-size: var(--fs-13); text-transform: uppercase; letter-spacing: .05em; font-weight: 800; color: var(--muted);
}
.admin-edit-card p.admin-edit-card__hint { margin: 0 0 16px; font-size: var(--fs-11_5); color: var(--muted); line-height: 1.5; }
.admin-edit-card + .admin-edit-card { margin-top: 0; }
.admin-edit-actions { display: flex; gap: 10px; }
.admin-edit-actions .btn { flex: 1; text-align: center; }
@media (max-width: 900px) {
  .admin-edit-layout { grid-template-columns: 1fr; }
  .admin-edit-side { position: static; }
}

/* V.054 — WordPress-style Tags chip input + hierarchical taxonomy
   quick-add (owner: "tags ko ... input window jese wordpress mein hey" /
   "quick search bhi ho ... user can add from here ... ye sab ajax ho").
   Backs `assets/js/taxonomy-picker.js`, used on the Product form's
   sidebar taxonomy postboxes. */
.tax-chip-input {
  border: 1px solid var(--line); border-radius: 10px; padding: 6px;
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center; background: #fff;
}
.tax-chip-input:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--soft); }
.tax-chip-input__chips { display: flex; flex-wrap: wrap; gap: 6px; }
.tax-chip {
  background: var(--soft); color: var(--accent); border-radius: 999px; padding: 4px 6px 4px 10px;
  font-size: var(--fs-12); font-weight: 700; display: flex; align-items: center; gap: 6px; line-height: 1.4;
}
.tax-chip button {
  border: none; background: none; cursor: pointer; font-weight: 800; line-height: 1;
  padding: 0 2px; color: inherit; font-size: var(--fs-13);
}
.tax-chip-input__field { border: none; outline: none; flex: 1; min-width: 100px; font-size: var(--fs-13); padding: 4px; }
.tax-chip--pending { opacity: .55; }
input.tax-filter { font-size: var(--fs-12); padding: 6px 10px; }
[data-tax-row][hidden] { display: none; }

/* V.055 — Attributes tab search-to-add results dropdown
   (assets/js/attribute-picker.js). */
[data-attr-search-results] {
  position: absolute; z-index: 20; left: 0; right: 0; max-width: 340px;
  background: #fff; border: 1px solid var(--line); border-radius: 10px;
  box-shadow: var(--shadow); margin-top: 4px; max-height: 220px; overflow-y: auto;
  display: none;
}
/* V.117 hotfix — Related tab search-to-add results dropdown
   (assets/js/related-picker.js, products/form.php + services/form.php).
   This reuses the exact same `.attr-picker-result` buttons as the
   Attributes search above, but `[data-related-results]` itself was never
   given the matching floating-card treatment — it only ever had the
   inline `position:relative;max-width:380px` on its wrapper div, so
   results rendered as plain unboxed stacked text that shoved the rest of
   the sidebar down instead of floating over it. Real, reproducible bug
   (owner report: "ajax not loading where it should have to, no distance
   maintained") — confirmed live via the AJAX search itself firing fine
   and returning real results, just with zero container styling. */
[data-related-results] {
  position: absolute; z-index: 20; left: 0; right: 0; max-width: 380px;
  background: #fff; border: 1px solid var(--line); border-radius: 10px;
  box-shadow: var(--shadow); margin-top: 4px; max-height: 220px; overflow-y: auto;
  display: none;
}
.attr-picker-result {
  display: block; width: 100%; text-align: left; border: none; background: none;
  padding: 8px 12px; font-size: var(--fs-13); cursor: pointer; font-family: inherit;
}
.attr-picker-result:hover { background: var(--soft); }
.attr-picker-result--empty { color: var(--muted); cursor: default; }
.attr-picker-result--empty:hover { background: none; }

/* V.057 — `.menu-item-row` was previously only styled via an inline
   <style> block local to admin/menus/form.php; V.056's Related-products
   picker reused the class name (for the same drag-reorder look) but had
   no styling of its own since it lives in products/form.php. Promoted to
   a real shared class here instead of copy-pasting the same <style>
   block into every screen that wants this look (DECISIONS.md #076).
   V.111 — `flex-wrap: wrap` added (plus the `.field` min-width below):
   the new "Add menu items" source panel sits beside this tree now
   (`.menu-builder-grid`), so the tree column is narrower than it used to
   be full-width — without wrap, the label/url inputs were squeezed down
   to a few unusable pixels wide at 1280px. Wrapping lets the label/url
   fields drop to their own line under the handle/badge/buttons instead of
   being crushed. */
.menu-item-row { display:flex; flex-wrap: wrap; align-items:center; gap:10px; background:#fff; border:1px solid var(--line); border-radius:8px; padding:10px 12px; margin-bottom:8px; cursor:grab; }
.menu-item-row.dragging { opacity:.4; }
.menu-item-row.drag-over { border-color: var(--accent); box-shadow: 0 0 0 3px var(--soft); }
.menu-item-row .handle { color:#b6bec7; font-size: 16px; /* decorative drag-handle glyph */ letter-spacing:2px; user-select:none; }
.menu-item-row .field { flex: 1 1 150px; min-width: 150px; margin:0; }
.menu-item-row .field input { width:100%; }

/* V.077 — WordPress-style nested Menu Builder rewrite (DECISIONS.md #100).
   Scoped, additive classes only — `.menu-item-row` itself (and its
   dragging/drag-over/handle/field rules above) stays untouched so the
   Related-products picker and the media-bucket widget, which already
   reuse that base class, are unaffected. */
.menu-tree { display: flex; flex-direction: column; }
.menu-tree__group { display: flex; flex-direction: column; }
.menu-tree__children { display: flex; flex-direction: column; margin-left: 34px; padding-left: 14px; border-left: 2px dashed var(--line); }
.menu-tree .menu-item-row--child { background: var(--soft); }
.menu-tree .menu-item-row--nest-target { border-color: var(--accent); box-shadow: 0 0 0 3px var(--soft); background: var(--soft); }
.menu-item-row__level-badge { font-size: var(--fs-10); text-transform: uppercase; letter-spacing: .04em; color: var(--muted); background: var(--bg); border: 1px solid var(--line); border-radius: 4px; padding: 2px 6px; white-space: nowrap; }
/* V.110 orphan cleanup — `.menu-item-row__nest-hint` and
   `.menu-tree-empty-children` removed here: verified zero references
   anywhere in resources/views, app/**/*.php, or assets/js/**/*.js (the
   real nested Menu Builder markup — `menu-tree`/`menu-tree__group`/
   `menu-tree__children`/`menu-item-row--child`/`menu-item-row--nest-
   target`/`menu-item-row__level-badge`/`menu-item-add-sub` above and
   below — never emits either class). See `app/Support/UiKitAudit.php`'s
   live orphan report. */
.menu-item-add-sub { font-size: var(--fs-12); }

/* V.111 → V.112 rewrite — WordPress-style "Add menu items" source panel
   (owner V.111: rebuild the "too basic" Menu Builder; owner V.112: "menu
   builder ko koi jaan do bilkul hi halka UI/UX hai, full page kar do, na do
   side bar, neechey sticky save button de do" — full page, no sidebar
   column, sticky bottom save bar).

   The V.111 version put the source panel + tree inside `.admin-edit-main`,
   itself squeezed to `1fr` next to a 320px `.admin-edit-side` Save column —
   flat pill tabs, a plain checkbox list, two separate white cards with no
   real visual distinction from the page background. V.112 removes that
   whole 2-column shell for this screen (`form.php` no longer uses
   `.admin-edit-layout`/`.admin-edit-side` at all — see its own V.112
   comment) and rebuilds the hierarchy instead of just widening it:
     - `#app-main-content:has(.menu-builder-page)` lifts the shared 1100px
       admin-content cap for this one screen only, so the source panel and
       tree finally get real room instead of splitting a narrow column.
     - the source panel and tree are now ONE bordered/shadowed unit
       (`.menu-builder-grid`) with an internal divider, not two separate
       floating cards — a fixed 360px left rail with a distinct `--bg`
       backdrop tint (vs. the tree's `--surface` white) makes the "pick
       from here → lands over there" relationship read at a glance instead
       of two same-colored boxes with no relationship implied.
     - tabs get a real active underline + icon-less but bolder pill instead
       of a flat outline, and the list rows get hover feedback.
     - Save/Cancel move out of any column into `.menu-builder-savebar`,
       fixed to the bottom of the viewport (not just this card), full
       width of the content area, elevated with a shadow — the owner's
       explicit "neechey sticky save button" ask. */
#app-main-content:has(.menu-builder-page) { max-width: none; }
.menu-builder-page { display: flex; flex-direction: column; gap: 22px; padding-bottom: 88px; }
.menu-builder-name-card { max-width: 560px; }

.menu-builder-grid {
  display: grid; grid-template-columns: 360px 1fr;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  box-shadow: var(--shadow); overflow: hidden; align-items: stretch;
}
@media (max-width: 900px) {
  .menu-builder-grid { grid-template-columns: 1fr; }
}
.menu-source-panel {
  background: var(--bg); border-right: 1px solid var(--line);
  padding: 24px; display: flex; flex-direction: column; min-width: 0;
}
@media (max-width: 900px) {
  .menu-source-panel { border-right: none; border-bottom: 1px solid var(--line); }
}
.menu-source-panel h3 {
  margin: 0 0 16px; font-size: var(--fs-13); text-transform: uppercase;
  letter-spacing: .05em; font-weight: 800; color: var(--muted);
}
.menu-builder-grid .menu-tree-card.admin-edit-card {
  padding: 24px; min-width: 0; border: none; box-shadow: none; border-radius: 0; margin: 0;
}
.menu-tree-card .field-legend { font-size: var(--fs-13); text-transform: uppercase; letter-spacing: .05em; }

.menu-source-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; border-bottom: 1px solid var(--line); padding-bottom: 14px; }
.menu-source-tab {
  border: 1px solid var(--line); background: var(--surface); color: var(--muted); border-radius: 999px;
  padding: 6px 13px; font-size: var(--fs-11_5); font-weight: 700; cursor: pointer; transition: background .12s, color .12s, border-color .12s;
}
.menu-source-tab:hover { border-color: var(--accent); color: var(--accent); }
.menu-source-tab.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.menu-source-search { width: 100%; margin-bottom: 10px; }
.menu-source-list {
  max-height: 360px; overflow-y: auto; border: 1px solid var(--line); border-radius: 8px;
  padding: 4px 10px; margin-bottom: 12px; background: var(--surface);
}
.menu-source-item {
  display: flex; align-items: center; gap: 8px; padding: 8px 4px; font-size: var(--fs-12_5);
  cursor: pointer; border-bottom: 1px solid var(--line); border-radius: 6px; transition: background .1s;
}
.menu-source-item:hover { background: var(--soft); }
.menu-source-item:last-child { border-bottom: none; }
.menu-source-item input[type="checkbox"] { margin: 0; flex-shrink: 0; }
.menu-source-add { width: 100%; text-align: center; }
.menu-custom-link-form { margin-top: 18px; padding-top: 18px; border-top: 1px dashed var(--line); }
.menu-custom-link-form .field { margin-bottom: 10px; }
.menu-custom-link-form .field label { display: block; font-size: var(--fs-11_5); color: var(--muted); margin-bottom: 3px; }
.menu-custom-link-form #customLinkAdd { width: 100%; }

/* Sticky bottom save bar (owner: "neechey sticky save button de do").
   Fixed to the viewport bottom, offset by the real 250px sidebar width so
   it never overlaps the nav — collapses to left:0 at the same 900px
   breakpoint the sidebar itself goes off-canvas at. Safe-area padding for
   iOS home-indicator devices; the page's own `padding-bottom` above keeps
   the last tree row from ever sitting underneath it. */
.menu-builder-savebar {
  position: fixed; left: 250px; right: 0; bottom: 0; z-index: 30;
  background: var(--surface); border-top: 1px solid var(--line);
  box-shadow: 0 -6px 18px rgba(15, 23, 42, .08);
}
.menu-builder-savebar__inner {
  display: flex; justify-content: flex-end; gap: 10px;
  max-width: 1100px; margin: 0 auto; padding: 14px 28px;
  padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px));
}
.menu-builder-savebar .btn { min-width: 120px; text-align: center; }
@media (max-width: 900px) {
  .menu-builder-savebar { left: 0; }
  .menu-builder-savebar__inner { padding: 12px 16px; padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
}

/* V.113 (owner: "publish bar sticky, scroll karne per save option nechay
   aaye") — Product/Service form's Publish box, reusing the exact
   `.menu-builder-savebar` sticky-bottom-bar CSS above rather than
   inventing a second bar pattern. `.product-savebar` only adds the Status
   select alongside Cancel/Save (the menu bar has neither) and left-aligns
   it so Cancel/Save still sit flush right. `.wizard-form` gets bottom
   padding so the bar never overlaps the last tab panel's own content —
   same role `.menu-builder-page`'s own `padding-bottom: 88px` plays. */
.wizard-form { padding-bottom: 90px; }
.product-savebar .menu-builder-savebar__inner { justify-content: space-between; align-items: center; }
.product-savebar__status { display: flex; align-items: center; gap: 8px; margin: 0; }
.product-savebar__status label { margin: 0; font-size: var(--fs-12); font-weight: 700; color: var(--muted); }
.product-savebar__status select { border: 1px solid var(--line); border-radius: var(--rs); padding: 7px 10px; font: inherit; font-size: var(--fs-13); background: #fff; }
@media (max-width: 640px) {
  .product-savebar .menu-builder-savebar__inner { flex-wrap: wrap; }
  .product-savebar__status { order: -1; width: 100%; }
}

/* V.057 — universal media-bucket widget (assets/js/media-bucket.js).
   One shared grid/dropzone/card/status look for every Gallery/Videos/
   Downloads/Certificates section (Product, Service, Blog) and the Page
   featured image — replacing the old plain <input type=file multiple> +
   giant "attach existing" checkbox table (DECISIONS.md #076). Also used,
   in a simpler no-grid "library" mode, by the Media Library's own upload
   panel. */
/* --- V.179 redesign: slim add-bar first, then a clean square-tile grid.
   `--mt-amber` is the cover/featured accent (distinct from the blue
   --accent so "which one is the cover" reads at a glance). --- */
.media-bucket { --mt-amber: #e8892b; }

/* Slim "＋ Add …" bar (doubles as the dropzone). Grows into a tall empty-
   state dropzone only when the bucket has no items (.media-bucket.is-empty). */
.media-bucket-add {
  display: flex; align-items: center; gap: 12px; cursor: pointer;
  border: 1.5px dashed #c3d0e6; border-radius: 11px; padding: 11px 14px; margin-bottom: 10px;
  background: linear-gradient(180deg, #f7f9ff, #eef3ff); transition: border-color .15s, background .15s;
}
.media-bucket-add:hover, .media-bucket-add:focus-visible { border-color: var(--accent); outline: none; }
.media-bucket-add.is-dragover { border-color: var(--accent); background: #fff; box-shadow: 0 0 0 3px var(--soft); }
.media-bucket-add__plus {
  width: 34px; height: 34px; flex: 0 0 auto; border-radius: 9px; background: #fff;
  border: 1px solid #dbe6ff; color: var(--accent); display: inline-flex; align-items: center; justify-content: center;
}
.media-bucket-add__text { display: flex; flex-direction: column; line-height: 1.3; }
.media-bucket-add__text b { font-size: var(--fs-14); }
.media-bucket-add__hint { font-size: var(--fs-12); color: var(--muted); }
.media-bucket-add__empty { display: none; }
/* Empty state — the add-bar becomes a proper big dropzone. */
.media-bucket.is-empty .media-bucket-add {
  flex-direction: column; text-align: center; padding: 30px 16px; gap: 8px;
}
.media-bucket.is-empty .media-bucket-add__hint { display: none; }
.media-bucket.is-empty .media-bucket-add__empty { display: block; font-size: var(--fs-12); color: var(--muted); }

.media-bucket-search { position: relative; margin-bottom: 12px; }
.media-bucket-search input {
  width: 100%; border: 1px solid var(--line); border-radius: 9px; padding: 9px 12px;
  font: inherit; font-size: var(--fs-13); background: #fff;
}
[data-media-bucket-search-results] {
  position: absolute; z-index: 20; left: 0; right: 0; max-width: 100%;
  background: #fff; border: 1px solid var(--line); border-radius: 10px;
  box-shadow: var(--shadow); margin-top: 4px; max-height: 220px; overflow-y: auto;
  display: none;
}

/* Tile grid — uniform squares that fill their columns (no more small cards
   scattered inside wide cells). */
.media-bucket-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
  gap: 12px;
}
.media-bucket-grid:empty { display: none; }
.media-tile {
  position: relative; aspect-ratio: 1 / 1; border: 1px solid var(--line); border-radius: 10px;
  overflow: hidden; background: #eef1f4; cursor: grab;
}
.media-tile__thumb { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.media-tile__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.media-tile__icon { font-size: 30px; opacity: .7; }
.media-tile.dragging { opacity: .4; }
.media-tile.drag-over { border-color: var(--accent); box-shadow: 0 0 0 3px var(--soft); }
.media-tile.is-pending, .media-tile.is-failed { cursor: default; }
.media-tile.is-failed { border-color: #f3c9c9; background: #fff8f8; }
.media-tile.is-cover { outline: 2px solid var(--mt-amber); outline-offset: -2px; }

/* Hover scrim so the white/red controls stay legible over any image. */
.media-tile::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 1;
  background: linear-gradient(180deg, rgba(15,23,40,.28), rgba(15,23,40,0) 34%, rgba(15,23,40,0) 60%, rgba(15,23,40,.5));
  opacity: 0; transition: opacity .15s;
}
.media-tile:hover::after { opacity: 1; }

.media-tile__drag {
  position: absolute; top: 6px; left: 6px; z-index: 2; width: 24px; height: 24px; border-radius: 7px;
  background: rgba(255,255,255,.92); color: var(--muted); display: flex; align-items: center; justify-content: center;
  cursor: grab; font-size: 13px; opacity: 0; transition: opacity .15s;
}
.media-tile__del {
  position: absolute; top: 6px; right: 6px; z-index: 2; width: 24px; height: 24px; border-radius: 7px;
  background: rgba(224,72,72,.95); color: #fff; border: none; display: flex; align-items: center; justify-content: center;
  cursor: pointer; font-size: 12px; opacity: 0; transition: opacity .15s;
}
.media-tile:hover .media-tile__drag, .media-tile:hover .media-tile__del,
.media-tile.is-failed .media-tile__del { opacity: 1; }
.media-tile__setcover {
  position: absolute; left: 6px; right: 6px; bottom: 6px; z-index: 2; border: none; border-radius: 7px;
  padding: 5px; background: rgba(255,255,255,.95); color: var(--ink); font: inherit; font-weight: 800; font-size: 11px;
  cursor: pointer; opacity: 0; transition: opacity .15s;
}
.media-tile:hover .media-tile__setcover { opacity: 1; }
.media-tile.is-cover .media-tile__setcover { display: none; }
.media-tile__coverbadge {
  position: absolute; left: 6px; bottom: 6px; z-index: 2; display: none;
  background: var(--mt-amber); color: #fff; font-size: 10px; font-weight: 800; padding: 2px 7px; border-radius: 999px;
}
.media-tile.is-cover .media-tile__coverbadge { display: block; }
.media-tile.is-cover:hover .media-tile__coverbadge { display: none; }
.media-tile__stat {
  position: absolute; right: 6px; bottom: 6px; z-index: 2; font-size: 10px; font-weight: 800;
  padding: 2px 7px; border-radius: 999px;
}
.stat--opt { background: #fff3e6; color: var(--mt-amber); }
.stat--up { background: #eaf0ff; color: var(--accent); }
.stat--fail { background: #fdeaea; color: var(--danger); }
.media-tile__prog { position: absolute; left: 0; right: 0; bottom: 0; height: 4px; background: rgba(255,255,255,.55); z-index: 2; }
.media-tile__prog i { display: block; height: 100%; width: 0%; background: var(--accent); transition: width .15s ease; }
.media-tile__spinner {
  width: 22px; height: 22px; border-radius: 50%; border: 3px solid var(--line); border-top-color: var(--accent);
  animation: mt-spin .7s linear infinite;
}
@keyframes mt-spin { to { transform: rotate(360deg); } }
.media-tile__label {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; padding: 6px 8px;
  background: linear-gradient(180deg, rgba(15,23,40,0), rgba(15,23,40,.72));
  color: #fff; font-size: var(--fs-11); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.media-tile__error {
  position: absolute; left: 6px; right: 6px; bottom: 6px; z-index: 2; font-size: 10px; color: var(--danger);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.media-tile__edit {
  position: absolute; top: 6px; left: 50%; transform: translateX(-50%); z-index: 2;
  background: rgba(255,255,255,.92); color: var(--ink); font-size: 10px; font-weight: 700;
  padding: 2px 8px; border-radius: 999px; text-decoration: none; opacity: 0; transition: opacity .15s;
}
.media-tile:hover .media-tile__edit { opacity: 1; }
.media-tile.is-failed .media-tile__edit, .media-tile.is-pending .media-tile__edit { display: none; }
.media-bucket-count { font-size: var(--fs-12); color: var(--muted); margin: 10px 0 0; }

/* Featured / cover preview slot (Product Images sub-tab). */
.media-featured-row { display: grid; grid-template-columns: 210px 1fr; gap: 18px; margin-bottom: 20px; }
.media-featured__frame {
  position: relative; aspect-ratio: 4 / 3; border: 1px solid var(--line); border-radius: 12px; overflow: hidden;
  background: linear-gradient(160deg, #dde6f4, #b9cdec); display: flex; align-items: center; justify-content: center;
}
.media-featured__frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
.media-featured__placeholder { color: #7d93b8; font-weight: 700; font-size: var(--fs-13); }
.media-featured__badge {
  position: absolute; top: 8px; left: 8px; background: var(--mt-amber); color: #fff;
  font-size: 11px; font-weight: 800; padding: 4px 9px; border-radius: 999px;
}
.media-featured__foot { display: flex; gap: 8px; margin-top: 8px; }
.media-featured__foot button {
  flex: 1; border: 1px solid var(--line); background: #fff; border-radius: 8px; padding: 7px;
  font: inherit; font-weight: 700; font-size: 12px; cursor: pointer;
}
.media-featured__foot button:hover { border-color: var(--accent); color: var(--accent); }
.media-featured__note { font-size: var(--fs-13); color: var(--muted); align-self: center; }
.media-featured__note b { color: var(--ink); }
@media (max-width: 640px) { .media-featured-row { grid-template-columns: 1fr; } }

/* Media sub-tabs (Images · Videos · Files) inside the product Media tab. */
.media-subtabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 16px; border-bottom: 1px solid var(--line); padding-bottom: 12px; }
.media-subtab {
  display: inline-flex; align-items: center; gap: 8px; padding: 8px 14px; border-radius: 10px;
  font-weight: 700; font-size: var(--fs-13); color: var(--muted); cursor: pointer; border: 1px solid transparent; background: none;
}
.media-subtab:hover { color: var(--ink); }
.media-subtab.is-active { background: #fff; color: var(--accent); border-color: #d5e1ff; box-shadow: 0 2px 8px rgba(40,95,242,.12); }
.media-subtab__n { font-size: 11px; font-weight: 800; background: var(--soft); color: var(--muted); border-radius: 999px; padding: 1px 7px; }
.media-subtab.is-active .media-subtab__n { background: var(--accent); color: #fff; }
.media-subpanel[hidden] { display: none; }
.media-subpanel .section-title:first-child { margin-top: 0; }

/* Kept for the Media Library's own upload panel status rows only
   (initLibraryUpload still renders .media-bucket-card list rows). */
.media-bucket-card {
  position: relative; border: 1px solid var(--line); border-radius: 10px; background: #fff;
  padding: 10px 12px; display: flex; flex-direction: column; gap: 6px;
}
.media-bucket-card.is-failed { border-color: #f3c9c9; background: #fff8f8; }
.media-bucket-card__label { font-size: var(--fs-12); font-weight: 600; }
.media-bucket-card__meta { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.media-bucket-card__progress { height: 4px; border-radius: 2px; background: var(--line); overflow: hidden; }
.media-bucket-card__progress-bar { height: 100%; background: var(--accent); width: 0%; transition: width .15s ease; }
.media-bucket-card__error { font-size: var(--fs-11); color: var(--danger); }
/* Media Library panel reuses the add-bar as its dropzone. */
.media-bucket-dropzone {
  border: 2px dashed var(--line); border-radius: 10px; padding: 18px 14px; text-align: center;
  cursor: pointer; font-size: var(--fs-13); color: var(--muted); background: var(--soft);
}
.media-bucket-dropzone:hover, .media-bucket-dropzone:focus-visible { border-color: var(--accent); color: var(--text); }
.media-bucket-dropzone.is-dragover { border-color: var(--accent); background: #fff; box-shadow: 0 0 0 3px var(--soft); }

/* V.059 — WYSIWYG editor (assets/js/wysiwyg-editor.js, mounts Quill on
   `textarea[data-wysiwyg]`). Quill's own "Snow" theme CSS (vendored,
   public/assets/vendor/quill/quill.snow.css) supplies the toolbar/editor
   chrome; this just fits it into this app's existing `.field` rhythm and
   sets a sensible default height matching the textarea it replaces. */
.wysiwyg-editor {
  --wysiwyg-height: 220px;
  border: 1px solid var(--line); border-radius: 8px; overflow: hidden; background: #fff;
}
.wysiwyg-editor .ql-toolbar.ql-snow {
  border: none; border-bottom: 1px solid var(--line); background: var(--soft);
  border-radius: 8px 8px 0 0;
}
.wysiwyg-editor .ql-container.ql-snow { border: none; font-family: inherit; font-size: var(--fs-14); }
.wysiwyg-editor .ql-editor { min-height: var(--wysiwyg-height); }
.wysiwyg-editor .ql-editor.ql-blank::before { font-style: normal; color: var(--muted); }

/* Round D — UI Kit rebuild Phase 2 generic components (list row, gallery grid,
   sticky CTA bar, toast). toast.js is loaded on every admin screen; the other
   three currently render only inside this admin UI Kit demo page itself — kept
   here rather than in the frontend bundle since nothing on the live public
   site uses them yet (see the final report's judgment-call note). */
/* ===== Round D — UI Kit rebuild Phase 2 (DECISIONS.md #103): four real,
   generic components the live usage audit (App\Support\UiKitAudit)
   confirmed genuinely didn't exist yet — a compact List row, a Gallery/
   showcase grid, a Sticky/floating CTA bar, and a Toast notification.
   Same token set (--line/--r/--rs/--shadow/--accent/--ink/--muted/--soft/
   --surface) as every existing component, no new tokens introduced.
   These start as real, working, ready-to-adopt CSS (+ Toast's real JS —
   see assets/js/toast.js) — until a future round wires one into a real
   screen, the live audit will correctly show it at low/zero usage; that's
   an honest reflection of "built, not yet adopted", not a bug. ===== */

/* List row — a compact horizontal row (thumbnail + title/meta + actions),
   for lists that don't need a full <table> (e.g. a "recently viewed" or
   notification-style list). */
.list-row {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px;
  border: 1px solid var(--line); border-radius: var(--rs); background: var(--surface);
}
.list-row + .list-row { margin-top: 6px; }
.list-row__thumb {
  width: 36px; height: 36px; border-radius: 6px; object-fit: cover; flex-shrink: 0; background: var(--soft);
}
.list-row__body { flex: 1; min-width: 0; }
.list-row__title { font-size: var(--fs-13); font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list-row__meta { font-size: var(--fs-11); color: var(--muted); margin-top: 2px; }
.list-row__actions { display: flex; gap: 6px; flex-shrink: 0; }

/* Gallery / showcase grid — an even grid of media thumbnails with a
   hover caption, distinct from .grid (generic layout utility) and
   .media-bucket-grid (the upload widget) — this is for READ-ONLY
   showcase/portfolio-style display. */
.gallery-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px;
}
.gallery-grid__item {
  position: relative; border-radius: var(--rs); overflow: hidden; border: 1px solid var(--line);
  aspect-ratio: 1 / 1; background: var(--soft);
}
.gallery-grid__item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gallery-grid__caption {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 6px 8px; font-size: var(--fs-11); color: #fff;
  background: linear-gradient(0deg, rgba(0,0,0,.65), rgba(0,0,0,0)); opacity: 0; transition: opacity .15s;
}
.gallery-grid__item:hover .gallery-grid__caption { opacity: 1; }

/* Sticky / floating CTA bar — a full-width bar pinned to the bottom of
   the viewport, for a persistent call-to-action (distinct from
   .whatsapp-fab, which is a single round icon button, not a message +
   action bar). */
.sticky-cta {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 20px; background: var(--surface); border-top: 1px solid var(--line); box-shadow: 0 -8px 20px rgba(0,0,0,.08);
}
.sticky-cta__text { font-size: var(--fs-13); color: var(--ink); }
.sticky-cta__text .muted { display: block; font-size: var(--fs-11); }

/* Toast notification — a transient, JS-triggered message (see
   assets/js/toast.js's real window.OkamiToast.show()), distinct from
   .notice (a static, server-rendered, always-visible message block). */
.toast-region {
  position: fixed; right: 20px; bottom: 20px; z-index: 200;
  display: flex; flex-direction: column; gap: 8px; width: min(320px, calc(100vw - 40px));
}
.toast {
  display: flex; align-items: flex-start; gap: 8px; padding: 10px 12px;
  border-radius: var(--rs); background: var(--dark); color: #fff; font-size: var(--fs-13);
  box-shadow: var(--shadow); animation: okami-toast-in .18s ease-out;
}
.toast.success { background: var(--success); }
.toast.warning { background: var(--warning); color: var(--ink); }
.toast.danger { background: var(--danger); }
.toast__msg { flex: 1; }
.toast__close { background: none; border: none; color: inherit; opacity: .7; cursor: pointer; font-size: var(--fs-14); line-height: 1; padding: 0; }
.toast__close:hover { opacity: 1; }
@keyframes okami-toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }

/* V.107 — Header Settings screen (resources/views/admin/page-settings/
   header-settings.php): theme-picker preview cards, the logo panel, and
   section headings. Scoped under .hs- so nothing here leaks onto the
   generic page-settings/edit.php form other page types still use. */
.hs-section { margin-bottom: 28px; }
.hs-section:last-child { margin-bottom: 0; }
.hs-section h3 { margin: 0 0 4px; font-size: var(--fs-16); }
.hs-section .muted { margin: 0 0 12px; font-size: var(--fs-12); }

.hs-theme-cards { display: flex; gap: 14px; flex-wrap: wrap; }
.hs-theme-card {
  display: block; width: 220px; border: 2px solid var(--line); border-radius: var(--rs);
  padding: 10px; cursor: pointer; background: var(--surface);
}
.hs-theme-card input { position: absolute; opacity: 0; pointer-events: none; }
.hs-theme-card:has(input:checked), .hs-theme-card.is-selected { border-color: var(--accent); box-shadow: 0 0 0 3px var(--soft); }
.hs-theme-card__preview {
  border-radius: 8px; overflow: hidden; border: 1px solid var(--line); margin-bottom: 8px;
}
.hs-theme-card__bar { height: 10px; }
.hs-theme-card__nav { height: 22px; display: flex; align-items: center; gap: 6px; padding: 0 8px; }
.hs-theme-card__nav span { display: inline-block; height: 6px; border-radius: 3px; background: currentColor; opacity: .5; }
.hs-theme-card__nav span:first-child { width: 28px; opacity: .9; }
.hs-theme-card__nav span:not(:first-child) { width: 14px; }
.hs-theme-card--clean .hs-theme-card__bar { background: var(--soft); }
.hs-theme-card--clean .hs-theme-card__nav { background: var(--surface); color: var(--ink); border-top: 1px solid var(--line); }
.hs-theme-card--bold .hs-theme-card__bar { background: var(--dark); }
.hs-theme-card--bold .hs-theme-card__nav { background: var(--dark); color: #fff; }
.hs-theme-card__label { font-weight: 750; font-size: var(--fs-13); }
.hs-theme-card__desc { font-size: var(--fs-11_5); color: var(--muted); }

.hs-logo-row { display: flex; align-items: center; gap: 16px; margin-bottom: 12px; }
.hs-logo-preview {
  width: 96px; height: 96px; border: 1px solid var(--line); border-radius: var(--rs);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
  background: var(--bg); flex-shrink: 0;
}
.hs-logo-preview img { max-width: 100%; max-height: 100%; object-fit: contain; }

.hs-menu-row { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; }
.hs-menu-row .field { flex: 1; min-width: 220px; margin: 0; }

/* ===== Phase D — final phase of the admin-panel visual revamp: a real
   toggle-switch component + grouped Settings section cards (owner
   reference: mobile Settings before/after screenshot — flat plain list →
   bold section labels, each row its own white card, icon-in-soft-circle,
   chevron/toggle on the right). ===== */

/* Real toggle switch. Replaces the plain-checkbox rendering the `toggle`
   PageSettingsSchema field type used to emit everywhere (page-settings/
   edit.php + header-settings.php's shared $renderControl closure — both
   updated to this same markup, so it's one component, not a Settings-only
   one-off). The real <input type="checkbox"> stays in the DOM, keyboard-
   focusable and submitting exactly as before — only visually hidden and
   restyled via its sibling track, the same "hide the real control, style
   the sibling" technique `.pill-toggle` above already uses, so this stays
   a real accessible form control under the hood, not a JS-only fake. */
.toggle-switch { position: relative; display: inline-flex; align-items: center; flex-shrink: 0; cursor: pointer; }
.toggle-switch input {
  position: absolute; inset: 0; width: 44px; height: 24px; margin: 0; opacity: 0; cursor: pointer;
}
.toggle-switch__track {
  display: block; width: 44px; height: 24px; border-radius: 999px; background: #d7dde3; border: 1px solid var(--line);
  position: relative; flex-shrink: 0; transition: background .15s ease, border-color .15s ease;
}
.toggle-switch__track::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(15, 22, 29, .3); transition: transform .15s ease;
}
.toggle-switch input:checked + .toggle-switch__track { background: var(--success); border-color: var(--success); }
.toggle-switch input:checked + .toggle-switch__track::after { transform: translateX(20px); }
.toggle-switch input:focus-visible + .toggle-switch__track { outline: 2px solid var(--accent); outline-offset: 2px; }
.toggle-switch input:disabled + .toggle-switch__track { opacity: .5; cursor: not-allowed; }
.toggle-switch input:disabled { cursor: not-allowed; }

/* A toggle field rendered inside the generic `.field` label+control stack
   (Page Content edit forms, Header Settings' "Other header settings"
   group, popup/homepage toggles) — label and switch share one row instead
   of stacking, so it doesn't read as two separate labels. */
.field--toggle { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.field--toggle label { margin: 0; }

/* Grouped Settings section cards. `.settings-group` is one labelled
   cluster on a Settings tab; `.settings-row` is a single-value setting
   (toggle/short text/select) rendered as its own small white card — icon
   in a soft tinted circle, label + optional one-line hint, control on the
   right. Reserved for fields simple enough to read on one line, per the
   revamp plan's own guidance — a field that needs real room (a textarea,
   a color picker pair, a repeater, IndexNow's read-only key + regenerate
   button) uses `.settings-card` instead, a bigger card with the same
   icon-circle head but its normal `.field` stack of controls below. */
.settings-group { margin-bottom: 26px; }
.settings-group:last-child { margin-bottom: 0; }
.settings-group__label {
  font-size: var(--fs-11); font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
  color: var(--accent); margin: 0 0 10px; padding: 0 2px;
}
.settings-cards { display: flex; flex-direction: column; gap: 10px; }
.settings-row__icon, .settings-card__head .settings-row__icon {
  width: 36px; height: 36px; border-radius: 10px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
}
.settings-row__icon svg { width: 18px; height: 18px; }
.settings-row__icon[data-tint="a"] { background: var(--tint-a-bg); color: var(--tint-a-ink); }
.settings-row__icon[data-tint="b"] { background: var(--tint-b-bg); color: var(--tint-b-ink); }
.settings-row__icon[data-tint="c"] { background: var(--tint-c-bg); color: var(--tint-c-ink); }
.settings-row__icon[data-tint="d"] { background: var(--tint-d-bg); color: var(--tint-d-ink); }

.settings-row {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--rs);
  box-shadow: var(--shadow); padding: 14px 16px; display: flex; align-items: center; gap: 12px;
}
.settings-row--toggle { flex-wrap: nowrap; }
.settings-row__body { flex: 1; min-width: 0; }
.settings-row__body label { display: block; font-size: var(--fs-13); font-weight: 750; margin: 0; }
.settings-row__hint { margin: 3px 0 0; font-size: var(--fs-11_5); color: var(--muted); line-height: 1.4; }
.settings-row__control { flex-shrink: 0; display: flex; align-items: center; }
.settings-row__control input[type="text"],
.settings-row__control input[type="email"],
.settings-row__control input[type="url"],
.settings-row__control select {
  border: 1px solid var(--line); border-radius: var(--rs); padding: 8px 10px; font: inherit;
  background: #fff; width: 190px; max-width: 42vw;
}
.settings-row__control input:focus-visible, .settings-row__control select:focus-visible {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--soft);
}
@media (max-width: 480px) {
  /* Text/select controls need real typing room a phone-width card can't
     spare next to the icon + label, so — unlike the reference screenshot's
     pure nav/toggle rows — an input-type settings row wraps its control
     onto its own full-width line below, indented to align under the
     label. Toggle rows (`.settings-row--toggle`) need no such room, so
     they stay exactly one line, matching the reference. */
  .settings-row--input { flex-wrap: wrap; }
  .settings-row--input .settings-row__control { width: 100%; margin-top: 8px; padding-left: 48px; }
  .settings-row--input .settings-row__control input,
  .settings-row--input .settings-row__control select { width: 100%; max-width: none; }
}

.settings-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  box-shadow: var(--shadow); padding: 18px 18px 20px;
}
.settings-card__head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.settings-card__head-text strong { display: block; font-size: var(--fs-14); font-weight: 750; }
.settings-card__head-text p { margin: 2px 0 0; font-size: var(--fs-11_5); color: var(--muted); line-height: 1.4; }
.settings-card .field { margin: 0 0 14px; }
.settings-card .field:last-child { margin-bottom: 0; }
/* A long unbroken value (IndexNow's generated key/URL, a pasted token)
   inside a hint must not push the whole mobile-width card wider than its
   viewport — this is the one thing every other admin-shell.css rule above
   already assumes wraps as normal prose. */
.settings-row__hint code, .settings-card p code { overflow-wrap: anywhere; word-break: break-word; }

/* PHASE 7 — highlight a setting field when the admin search jumps to it
   (e.g. /admin/settings#f-inquiry-whatsapp-number). */
input:target, select:target, textarea:target{
  outline:3px solid var(--accent, #285ff2); outline-offset:3px; border-radius:8px;
  animation: settingFlash 1.6s ease 1;
}
@keyframes settingFlash{ 0%,60%{ box-shadow:0 0 0 4px color-mix(in srgb, var(--accent,#285ff2) 30%, transparent); } 100%{ box-shadow:none; } }

/* PHASE 8 — term-tree bulk select + toolbar (bulk edit/delete). */
.term-toolbar { display: flex; align-items: center; gap: 16px; margin-bottom: 12px; flex-wrap: wrap; }
.term-toolbar .admin-search { flex: 0 0 auto; }
.term-selectall { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-13, 13px); color: var(--muted); font-weight: 600; cursor: pointer; }
.term-selectall input { width: 16px; height: 16px; accent-color: var(--accent); }
.bulk-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  background: var(--soft); border: 1px solid var(--accent); border-radius: 10px; padding: 10px 14px; margin-bottom: 12px; }
.bulk-bar__count { font-size: var(--fs-13, 13px); color: var(--ink); font-weight: 600; }
.bulk-bar__count b { color: var(--accent); }
.bulk-bar__actions { display: flex; gap: 8px; }
.term-check { width: 16px; height: 16px; flex: 0 0 auto; accent-color: var(--accent); cursor: pointer; }

/* ============================================================
   V.174 — product form sidebar taxonomy postboxes (Brand /
   Product Category / Vehicle Type ...). Before this, the
   `.tax-filter` search input carried no border/width and the
   term checkboxes were raw browser controls — they read as
   "orphan" fields. This gives them the same rounded, accented
   language as the rest of the admin form + a real interactive
   check-row (hover, selected state, custom accent checkbox).
   ============================================================ */
input.tax-filter,
input[type="search"].tax-filter,
input[type="text"].tax-filter {
  width: 100%; box-sizing: border-box;
  border: 1px solid var(--line); border-radius: 9px;
  padding: 8px 11px; font: inherit; font-size: var(--fs-13);
  background: #fff; color: var(--ink);
  transition: border-color .12s ease, box-shadow .12s ease;
}
input.tax-filter::placeholder { color: var(--muted); }
input.tax-filter:focus-visible,
input.tax-filter:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--soft);
}

/* Term tree — inset scroll panel so the list reads as one grouped control. */
[data-tax-tree] {
  border: 1px solid var(--line); border-radius: 10px;
  padding: 4px; background: #fcfdff;
}

/* Interactive check-row: full-width hit area, hover + selected states. */
.checkrow {
  display: flex; align-items: center; gap: 9px;
  font-size: var(--fs-13); padding: 7px 9px; margin: 1px 0;
  border-radius: 8px; cursor: pointer;
  transition: background .12s ease;
}
.checkrow:hover { background: var(--soft); }
.checkrow label { cursor: pointer; flex: 1; }
/* Custom accent checkbox — consistent across browsers. */
.checkrow input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  width: 17px; height: 17px; margin: 0; flex: 0 0 auto;
  border: 1.5px solid #c4ccdb; border-radius: 5px; background: #fff;
  cursor: pointer; position: relative;
  transition: background .12s ease, border-color .12s ease;
}
.checkrow input[type="checkbox"]:hover { border-color: var(--accent); }
.checkrow input[type="checkbox"]:checked {
  background: var(--accent); border-color: var(--accent);
}
.checkrow input[type="checkbox"]:checked::after {
  content: ""; position: absolute; left: 5px; top: 2px;
  width: 4px; height: 8px; border: solid #fff; border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.checkrow input[type="checkbox"]:focus-visible {
  outline: none; box-shadow: 0 0 0 3px var(--soft);
}
/* A checked row reads as selected even before hover. */
.checkrow:has(input[type="checkbox"]:checked) { background: var(--soft); }
.checkrow:has(input[type="checkbox"]:checked) label { color: var(--accent); font-weight: 700; }

/* Quick-add mini form inside a taxonomy postbox. */
[data-tax-add-form] input[type="text"],
[data-tax-add-form] select {
  width: 100%; box-sizing: border-box;
  border: 1px solid var(--line); border-radius: 9px;
  padding: 8px 11px; font: inherit; font-size: var(--fs-13); background: #fff;
}
[data-tax-add-form] input[type="text"]:focus-visible,
[data-tax-add-form] select:focus-visible {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--soft);
}

/* ============================================================
   V.175 — admin edit-form refresh. One shared visual system so
   the Product, Service and Blog editors read as "the same
   nature" and look considered. Everything keys off existing
   shared classes (.wizard-form / .tabs-nav / .wizard-health /
   .postbox / .field), so all three forms lift together.
   ============================================================ */

/* ---- Health / completion bar — FIX + refresh.
   The fill/track were <span>s (inline): width/height were ignored
   so the bar rendered 0-tall and the fill never showed. Force block
   layout and give it real presence. ---- */
.wizard-health {
  background: linear-gradient(180deg, #fff, #f7f9ff);
  border: 1px solid #e3e9f5; border-radius: 14px;
  padding: 15px 17px; margin-bottom: 18px;
  box-shadow: 0 1px 2px rgba(16,24,40,.04);
}
.wizard-health__row { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.wizard-health__row:last-child { margin-bottom: 0; }
.wizard-health__label {
  font-size: var(--fs-11); font-weight: 800; text-transform: uppercase;
  letter-spacing: .05em; color: var(--muted); width: 74px; flex: 0 0 auto;
}
.wizard-health__bar {
  display: block; flex: 1 1 auto; height: 12px;
  background: #eaeef6; border-radius: 999px; overflow: hidden; position: relative;
}
.wizard-health__fill {
  display: block; height: 100%; min-width: 12px;
  background: linear-gradient(90deg, #4f7bff, var(--accent));
  border-radius: 999px; transition: width .35s cubic-bezier(.4,0,.2,1);
}
.wizard-health__fill.is-complete { background: linear-gradient(90deg, #24c281, #1fa971); }
.wizard-health__pct {
  min-width: 46px; flex: 0 0 auto; text-align: right;
  font-size: var(--fs-15); font-weight: 900; color: var(--ink); font-variant-numeric: tabular-nums;
}
.wizard-health__steps { display: flex; flex-wrap: wrap; gap: 7px; }
.wizard-health__step-pct {
  font-size: var(--fs-11); padding: 4px 10px; border-radius: 999px;
  background: #eef1f6; color: var(--muted); font-weight: 700; border: 1px solid transparent;
  font-variant-numeric: tabular-nums;
}
.wizard-health__step-pct.is-complete { background: var(--soft); color: var(--accent); border-color: #d5e1ff; }

/* ---- Wizard step nav — modern pill row instead of a flat underline. ---- */
.wizard-form .tabs-nav {
  gap: 8px; border-bottom: none; padding: 6px;
  background: #f4f6fb; border: 1px solid #e6eaf3; border-radius: 14px;
  margin-bottom: 20px; position: sticky; top: 8px; z-index: 5;
}
.wizard-form .tabs-nav button {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 14px; border-radius: 10px; border: 1px solid transparent;
  margin-bottom: 0; color: var(--muted); font-size: var(--fs-13); font-weight: 700;
  transition: background .14s ease, color .14s ease, box-shadow .14s ease;
}
.wizard-form .tabs-nav button:hover { color: var(--ink); background: #fff; }
.wizard-form .tabs-nav button.active {
  color: var(--accent); background: #fff; border-color: #d5e1ff;
  box-shadow: 0 2px 8px rgba(40,95,242,.14); border-bottom-color: #d5e1ff;
}
.wizard-form .tabs-nav button.step-complete { color: #178a5a; }
.wizard-step-num {
  width: 22px; height: 22px; margin-right: 0; font-size: var(--fs-11);
  background: #e3e8f2; color: var(--muted);
}
.wizard-form .tabs-nav button.active .wizard-step-num { background: var(--accent); color: #fff; }
.wizard-form .tabs-nav button.step-complete .wizard-step-num { background: #1fa971; color: #fff; }
.wizard-form .tabs-nav button[data-tab-target="review"] { margin-left: auto; }

/* ---- Postboxes — softer cards, tinted headers. ---- */
.postbox {
  border-radius: 14px; border-color: #e6eaf3;
  box-shadow: 0 1px 2px rgba(16,24,40,.04);
}
.postbox-header {
  padding: 12px 15px; background: linear-gradient(180deg, #fbfcfe, #f5f7fb);
  border-bottom-color: #eceff5; font-size: var(--fs-12); color: #55617a;
}
.postbox-body { padding: 16px; }
.postbox-sidebar .postbox-header { letter-spacing: .05em; }

/* ---- Fields — a touch more room + a stronger label. ---- */
.field label { font-size: var(--fs-12); color: #384152; margin-bottom: 6px; }
.field input:not([type="checkbox"]):not([type="radio"]),
.field select, .field textarea { border-radius: 10px; padding: 10px 13px; }
.field input:not([type="checkbox"]):not([type="radio"]):hover,
.field select:hover, .field textarea:hover { border-color: #c4ccdb; }

/* ---- Step panels get a light card so content doesn't float. ---- */
.wizard-form .tab-panel.active {
  background: #fff; border: 1px solid #edf0f6; border-radius: 14px; padding: 20px 22px;
}
.wizard-form .tab-panel.active > h3:first-child,
.wizard-form .tab-panel.active > h4:first-child { margin-top: 0; }

/* ---- Save Progress inline bar — brighter. ---- */
.wizard-savebar {
  background: linear-gradient(180deg, #f4f8ff, var(--soft));
  border-color: #cbd8ff; border-radius: 12px; padding: 12px 14px;
}

/* ---- V.176 toggle switch (Settings) ---- */
.settings-switch{ display:inline-flex; align-items:center; gap:10px; cursor:pointer; user-select:none; }
.settings-switch input{ position:absolute; opacity:0; width:1px; height:1px; }
.settings-switch__track{ width:44px; height:26px; border-radius:999px; background:#d4dae6; position:relative; transition:background .16s ease; flex:0 0 auto; }
.settings-switch__thumb{ position:absolute; top:3px; left:3px; width:20px; height:20px; border-radius:50%; background:#fff; box-shadow:0 1px 3px rgba(0,0,0,.25); transition:transform .16s ease; }
.settings-switch input:checked + .settings-switch__track{ background:var(--accent); }
.settings-switch input:checked + .settings-switch__track .settings-switch__thumb{ transform:translateX(18px); }
.settings-switch input:focus-visible + .settings-switch__track{ box-shadow:0 0 0 3px var(--soft); }
.settings-switch__label{ font-size:var(--fs-13); font-weight:700; color:var(--ink); }

/* ==========================================================================
   V.180 — Lead Manager inbox (P2). Gmail/Outlook-style 3-pane view rendered
   by resources/views/admin/inquiries/index.php + _list.php + _read.php and
   driven by assets/js/admin-lead-manager.js. Uses the existing admin tokens
   (--line/--accent/--muted/--soft/--ink/--danger); the --st-* stage colours
   are local to this component.
   ========================================================================== */
.lm {
  --st-new:#285ff2; --st-contacted:#8a5cf6; --st-quoted:#e8892b; --st-won:#1fa971; --st-lost:#93a1b5; --lm-wa:#25d366;
  display:grid; grid-template-columns:196px 330px 1fr; gap:0;
  height:calc(100vh - 168px); min-height:520px;
  border:1px solid var(--line); border-radius:14px; overflow:hidden; background:#fff;
}
/* rail */
.lm__rail { border-right:1px solid var(--line); background:var(--soft, #f6f8fc); padding:12px 9px; overflow-y:auto; }
.lm-railitem { display:flex; align-items:center; gap:9px; padding:8px 10px; border-radius:9px; font-size:var(--fs-13); font-weight:600; color:var(--muted); cursor:pointer; }
.lm-railitem:hover { background:#eaeff8; }
.lm-railitem.on { background:#e9efff; color:var(--accent); font-weight:800; }
.lm-railitem__ico { font-size:13px; }
.lm-railitem__c { margin-left:auto; font-size:10.5px; font-weight:800; background:#e2e8f2; color:var(--muted); border-radius:999px; padding:1px 7px; }
.lm-railitem.on .lm-railitem__c { background:var(--accent); color:#fff; }
.lm-dot { width:8px; height:8px; border-radius:50%; flex:0 0 auto; }
.lm-railsep { height:1px; background:var(--line); margin:10px 6px; }
.lm-raillabel { font-size:10px; font-weight:800; letter-spacing:.1em; text-transform:uppercase; color:#9aa7b8; padding:4px 10px 2px; }

/* list */
.lm__list { border-right:1px solid var(--line); display:flex; flex-direction:column; min-width:0; background:#fff; }
.lm__listhead { padding:10px 12px; border-bottom:1px solid var(--line); }
.lm__search { width:100%; background:#f1f4f9; border:1px solid transparent; border-radius:8px; padding:8px 11px; font:inherit; font-size:var(--fs-12); }
.lm__search:focus { outline:none; border-color:var(--accent); background:#fff; }
.lm__listbody { flex:1; overflow-y:auto; }
.lm-lead { display:grid; grid-template-columns:auto 40px 1fr auto; gap:9px; padding:11px 12px 11px 16px; border-bottom:1px solid #eef1f6; cursor:pointer; position:relative; }
.lm-lead:hover { background:#f7f9fe; }
.lm-lead.sel { background:#eef4ff; box-shadow:inset 3px 0 0 var(--accent); }
.lm-lead.unread::before { content:""; position:absolute; left:6px; top:18px; width:7px; height:7px; border-radius:50%; background:var(--accent); }
.lm-lead__star { border:none; background:none; color:#c9d3e0; font-size:15px; cursor:pointer; align-self:flex-start; padding:0; line-height:1; margin-top:1px; }
.lm-lead__star.on { color:#e8892b; }
.lm-lead__thumb { width:40px; height:40px; border-radius:8px; overflow:hidden; background:#eef1f6; display:flex; align-items:center; justify-content:center; color:#b6c1d0; font-size:12px; }
.lm-lead__thumb img { width:100%; height:100%; object-fit:cover; }
.lm-lead__mid { min-width:0; }
.lm-lead__name { font-size:var(--fs-13); font-weight:700; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.lm-lead.unread .lm-lead__name { font-weight:900; }
.lm-lead__snip { font-size:var(--fs-12); color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-top:1px; }
.lm-lead__chips { display:flex; gap:5px; margin-top:6px; flex-wrap:wrap; }
.lm-chip { font-size:10px; font-weight:700; background:#f0f3f8; color:var(--muted); border-radius:6px; padding:2px 7px; }
.lm-chip.src-cart { background:#eafaf2; color:#1fa971; }
.lm-chip.src-form { background:#eef1ff; color:var(--accent); }
.lm-lead__right { display:flex; flex-direction:column; align-items:flex-end; gap:6px; }
.lm-lead__time { font-size:10.5px; color:#9aa7b8; white-space:nowrap; }
.lm-stpill { font-size:9.5px; font-weight:800; padding:2px 8px; border-radius:999px; color:#fff; text-transform:uppercase; letter-spacing:.03em; }
.st-new { background:var(--st-new); } .st-contacted { background:var(--st-contacted); } .st-quoted { background:var(--st-quoted); } .st-won { background:var(--st-won); } .st-lost { background:var(--st-lost); }
.lm-listempty { padding:32px 16px; text-align:center; color:var(--muted); font-size:var(--fs-13); }
.lm-pager { display:flex; gap:5px; flex-wrap:wrap; padding:12px; border-top:1px solid var(--line); }
.lm-pager__btn { border:1px solid var(--line); background:#fff; border-radius:7px; min-width:30px; padding:5px 8px; font:inherit; font-size:12px; font-weight:700; cursor:pointer; color:var(--muted); }
.lm-pager__btn.on { background:var(--accent); color:#fff; border-color:var(--accent); }

/* reading pane */
.lm__read { overflow-y:auto; background:#fff; min-width:0; }
.lm-empty { height:100%; display:flex; flex-direction:column; align-items:center; justify-content:center; color:var(--muted); gap:8px; }
.lm-empty__ico { font-size:34px; opacity:.5; }
.rd__top { padding:18px 22px 14px; border-bottom:1px solid var(--line); }
.rd__row1 { display:flex; align-items:center; gap:12px; }
.rd__ava { width:44px; height:44px; border-radius:12px; background:linear-gradient(150deg,#3f6ff5,#8a5cf6); color:#fff; font-weight:800; font-size:16px; display:flex; align-items:center; justify-content:center; flex:0 0 auto; }
.rd__who { min-width:0; flex:1; }
.rd__name { font-size:17px; font-weight:900; letter-spacing:-.01em; }
.rd__meta { font-size:var(--fs-12); color:var(--muted); }
.rd__replied { color:#1fa971; font-weight:800; }
.rd__staractions { display:flex; gap:8px; }
.rd-iconbtn { width:34px; height:34px; border-radius:9px; border:1px solid var(--line); background:#fff; color:var(--muted); cursor:pointer; font-size:14px; display:flex; align-items:center; justify-content:center; }
.rd-iconbtn.star.on { color:#e8892b; border-color:#f4d6ac; background:#fff8ef; }
.rd-pipe { display:flex; gap:6px; margin-top:16px; flex-wrap:wrap; }
.rd-pstep { flex:1; min-width:70px; text-align:center; font-size:11px; font-weight:800; padding:7px 6px; border-radius:8px; background:#f1f4f9; color:#9aa7b8; border:none; cursor:pointer; }
.rd-pstep.done { background:#e9f7f0; color:#1fa971; }
.rd-pstep.cur { background:var(--accent); color:#fff; box-shadow:0 4px 12px rgba(40,95,242,.3); }
.rd__body { padding:16px 22px 26px; display:flex; flex-direction:column; gap:15px; }
.rd__actions { display:flex; gap:8px; flex-wrap:wrap; }
.rd-btn { border:none; border-radius:9px; padding:9px 14px; font:inherit; font-weight:800; font-size:var(--fs-13); cursor:pointer; display:inline-flex; align-items:center; gap:7px; text-decoration:none; }
.rd-btn--wa { background:var(--lm-wa); color:#fff; } .rd-btn--mail { background:var(--accent); color:#fff; } .rd-btn--ghost { background:#fff; border:1px solid var(--line); color:var(--ink); }
.rd-btn:disabled { opacity:.55; cursor:default; }
.rd-compose { border:1px solid var(--line); border-radius:12px; padding:12px; display:flex; flex-direction:column; gap:8px; background:#fafbff; }
.rd-compose__subject, .rd-compose__body { border:1px solid var(--line); border-radius:9px; padding:9px 11px; font:inherit; font-size:var(--fs-13); width:100%; }
.rd-compose__foot { display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; }
.rd-compose__hint { font-size:11.5px; color:var(--muted); }
.rd-compose__btns { display:flex; gap:8px; }
.rd-compose__status { font-size:12px; color:var(--muted); }
.rd-compose__status.is-error { color:var(--danger); }
.rd-compose__noemail { font-size:var(--fs-13); color:var(--muted); margin:0; }
.rd-card { border:1px solid var(--line); border-radius:12px; overflow:hidden; }
.rd-card__h { font-size:10.5px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); padding:10px 14px; border-bottom:1px solid var(--line); background:#fafbff; }
.rd-li { display:flex; align-items:center; gap:12px; padding:10px 14px; border-bottom:1px solid #f0f3f8; }
.rd-li:last-child { border-bottom:none; }
.rd-li__img { width:46px; height:46px; border-radius:8px; background:#eef1f6; overflow:hidden; flex:0 0 auto; }
.rd-li__img img { width:100%; height:100%; object-fit:cover; }
.rd-li__n { flex:1; min-width:0; }
.rd-li__nm { font-size:var(--fs-13); font-weight:700; }
.rd-li__nm a { color:var(--ink); text-decoration:none; }
.rd-li__nm a:hover { color:var(--accent); text-decoration:underline; }
.rd-li__gone { font-size:10px; color:var(--danger); background:#fdeaea; border-radius:5px; padding:1px 6px; font-weight:700; }
.rd-li__sku { font-size:11.5px; color:var(--muted); }
.rd-li__note { font-size:12px; color:#5c6b7f; font-style:italic; margin-top:2px; }
.rd-li__qty { font-size:12px; font-weight:800; background:#eef1f6; border-radius:7px; padding:4px 10px; }
.rd-msg { background:#fafbff; border:1px solid var(--line); border-radius:12px; padding:13px 15px; font-size:var(--fs-13); color:#33414f; }
.rd-notes { padding:12px 14px; display:flex; flex-direction:column; gap:4px; }
.rd-notes__empty { font-size:12px; color:var(--muted); margin:0 0 6px; }
.rd-note { display:flex; gap:10px; padding:8px 0; border-bottom:1px solid #f0f3f8; }
.rd-note.is-email { background:#f6faff; border-radius:8px; padding:8px; }
.rd-note__a { width:26px; height:26px; border-radius:50%; background:#e9efff; color:var(--accent); font-size:11px; font-weight:800; display:flex; align-items:center; justify-content:center; flex:0 0 auto; }
.rd-note__t { font-size:12.5px; color:#33414f; }
.rd-note__m { font-size:11px; color:#9aa7b8; margin-top:2px; }
.rd-notes__add { display:flex; gap:8px; margin-top:6px; }
.rd-notes__add input { flex:1; border:1px solid var(--line); border-radius:9px; padding:8px 11px; font:inherit; font-size:var(--fs-13); }

/* responsive — collapse to stacked panes on narrow admin viewports */
@media (max-width:1080px) {
  .lm { grid-template-columns:1fr 1fr; height:auto; }
  .lm__rail { grid-column:1 / -1; display:flex; flex-wrap:wrap; gap:4px; }
  .lm__rail .lm-railsep, .lm__rail .lm-raillabel { display:none; }
  .lm-railitem { flex:0 0 auto; }
  .lm__list, .lm__read { max-height:70vh; }
}
@media (max-width:720px) {
  .lm { grid-template-columns:1fr; }
  .lm__read { border-top:1px solid var(--line); }
}

/* V.254 — line-icon baseline: every App\Support\Icons::svg() output carries
   .oki-svgic so admin chrome icons default to a clean 1em box. Specific
   containers (dashboard, inquiries rail, media tiles) size their own below. */
.oki-svgic{ width:1em; height:1em; vertical-align:-.15em; flex:0 0 auto; }
.lm-railitem__ico .oki-svgic{ width:15px; height:15px; }
.lm-lead__star .oki-svgic, .rd-iconbtn .oki-svgic{ width:16px; height:16px; }
.lm-chip .oki-svgic{ width:12px; height:12px; }
.lm-empty__ico .oki-svgic{ width:34px; height:34px; }
.media-tile__icon .oki-svgic, .mb-ic{ width:26px; height:26px; }
.media-tile__del .oki-svgic, .media-tile__drag .oki-svgic{ width:14px; height:14px; }
.media-featured__badge .oki-svgic, .media-tile__setcover .oki-svgic, .media-tile__coverbadge .oki-svgic{ width:12px; height:12px; }
.seo-ic, .seo-note .oki-svgic, .pill .oki-svgic{ width:14px; height:14px; vertical-align:-.15em; }
.seo-btn .oki-svgic{ width:15px; height:15px; }
.pt-applied .oki-svgic, .pt-note .oki-svgic, .pt-btn .oki-svgic{ width:14px; height:14px; }
.handle .oki-svgic{ width:16px; height:16px; color:#b6c1d4; }
.fb-svgic{ width:14px; height:14px; }
.pt-dot, .ub-livedot{ width:8px; height:8px; border-radius:50%; background:currentColor; display:inline-block; vertical-align:middle; }

/* ============================================================
   V.303 — Videos & Downloads module admin polish. The category
   manager was a bare <table>, whose per-cell borders left a broken,
   "orphan" divider that stopped short of the Delete column. These
   scoped classes give both list screens a clean, aligned, card-list
   look with full-width dividers and tidy filter + empty states.
   ============================================================ */
.vdmod-toolbar { display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:14px; }
.vdmod-toolbar .vdmod-toolbar__label { font-size:12px; font-weight:700; letter-spacing:.3px; text-transform:uppercase; color:var(--muted,#78716c); }
.vdmod-toolbar select { min-width:150px; }
.vdmod-toolbar .vdmod-toolbar__spacer { flex:1; }

.vdmod-empty { text-align:center; padding:44px 20px; color:var(--muted,#78716c); }
.vdmod-empty__ic { width:46px; height:46px; margin:0 auto 12px; border-radius:12px; display:grid; place-items:center; background:color-mix(in srgb, var(--accent,#c0392b) 10%, #fff); color:var(--accent,#c0392b); }
.vdmod-empty__ic svg { width:24px; height:24px; }
.vdmod-empty h4 { margin:0 0 4px; font-size:15px; color:var(--ink,#1c1917); }
.vdmod-empty p { margin:0 0 16px; font-size:13px; }

/* category manager */
.vdmod-cats { display:flex; flex-direction:column; margin:6px 0 2px; }
.vdmod-cat { display:flex; align-items:center; gap:12px; padding:11px 2px; border-bottom:1px solid var(--line,#e7e2dc); }
.vdmod-cat:last-child { border-bottom:none; }
.vdmod-cat__form { display:flex; align-items:center; gap:10px; flex:1; min-width:0; }
.vdmod-cat__form input[type=text] { flex:1; min-width:0; max-width:340px; }
.vdmod-cat__count { flex:none; min-width:30px; height:24px; padding:0 9px; border-radius:999px; background:var(--soft,#f4f1ec); color:var(--muted,#78716c); font-size:12px; font-weight:700; display:inline-flex; align-items:center; justify-content:center; }
.vdmod-cat__spacer { flex:1; }
.vdmod-catadd { display:flex; gap:8px; margin-top:16px; padding-top:16px; border-top:1px solid var(--line,#e7e2dc); max-width:440px; }
.vdmod-catadd input { flex:1; }
@media (max-width:640px){
  .vdmod-cat { flex-wrap:wrap; }
  .vdmod-cat__form { flex-basis:100%; }
}
