/* ============================================================
   admin.neuregami.com — the admin panel's entire stylesheet.

   It styles exactly what app.js and ui.js emit; their class vocabulary is the
   contract (public/js/views/README.md, "Class names"), not this file's taste.

   The palettes and the rail are copied out of assets/css/site.css rather than
   @imported: the admin shares the site's six themes and the same localStorage
   key, so a theme picked on the website carries over, but it does not share the
   site's marketing-page density or its components.

   Two colour worlds run through this file. The CANVAS is the mid-tone/dark
   working area; the PANEL is the pale rail colour, and it is where nearly all
   text actually lives. Components are written against --ink / --ink-2 / --line /
   --tint / --field / --fill / --link / --focus, and each panel container rebinds
   that set. Custom properties inherit, so one rule per container corrects every
   descendant without enumerating selectors.

   Overlay geometry (fixed position, z-index, the drawer's edge anchoring, the
   dt-wrap scroller) is set inline by ui.js so a message is never invisible when
   this file lags behind. Inline wins, so nothing here fights it — the rules
   below add colour, type, spacing and the one thing inline cannot do: the
   max-height that turns .dt-wrap into a real scrollport for its sticky header.

   Views may also reach for the extras at the end, all on the same tokens:
   .stats/.stat/.stat-n/.stat-k, .qcards/.qcard, .pcard/.pcard-img/.pcard-body/
   .pcard-name/.pcard-meta/.pcard-links/.pcard-sec, .gcards/.gcard/.gcard-badge/
   .gcard-dim, .card-actions, .row-actions, .cell-title/.cell-sub/.cell-clamp,
   .thumb/.thumb-empty, .tabs/.tab, .filters, .pager, .kv, .log/.log-row,
   .dropzone, .upload-row, .bar, .badge, .check/.checks, .switch, .note,
   .form-row, .mgrid/.mtile (aliases of .mediagrid/.mediatile), .mono/.muted/
   .trunc/.eyebrow/.sr.
   ============================================================ */

/* ---- palettes. Verbatim from site.css; 'ink' is the default. ---- */
html[data-dtheme="forest"]{ --rail-bg:#dae3da; --rail-ink:#2c3f33; --canvas:#54795f; --canvas-2:#4a6b54; --canvas-3:#3f5b48; --on-canvas:#dae3da; }
html[data-dtheme="slate"] { --rail-bg:#e4e8ee; --rail-ink:#263038; --canvas:#3a4756; --canvas-2:#323d4a; --canvas-3:#29323d; --on-canvas:#e4e8ee; }
html[data-dtheme="clay"]  { --rail-bg:#f2e7dc; --rail-ink:#5a3325; --canvas:#9a5b43; --canvas-2:#8a503a; --canvas-3:#774531; --on-canvas:#f7efe7; }
:root,
html[data-dtheme="ink"]   { --rail-bg:#e8e8e8; --rail-ink:#1a1c20; --canvas:#16181c; --canvas-2:#101216; --canvas-3:#0b0c0f; --on-canvas:#ececec; }
html[data-dtheme="plum"]  { --rail-bg:#eadfee; --rail-ink:#3b2c49; --canvas:#57406b; --canvas-2:#4c385e; --canvas-3:#402f4f; --on-canvas:#eadfee; }
html[data-dtheme="ocean"] { --rail-bg:#dceaec; --rail-ink:#143a42; --canvas:#1f5a66; --canvas-2:#1a4e59; --canvas-3:#16424b; --on-canvas:#dceaec; }

/* ---- token mapping: the CANVAS context, i.e. the document default ---- */
:root{
  --font-display:"Oswald","Helvetica Neue",Arial,sans-serif;
  --font-body:"Inter",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --font-mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;

  --rail-w:268px;
  --mbar-h:56px;
  --head-h:64px;
  --gut:clamp(16px,2.4vw,28px);
  --r-xs:6px; --r-sm:10px; --r:14px; --r-lg:20px; --r-xl:28px;
  --ease:cubic-bezier(.22,1,.36,1);
  --dur:.24s;
  --shadow:0 1px 2px rgba(0,0,0,.14), 0 10px 30px -14px rgba(0,0,0,.34);
  --shadow-lg:0 2px 6px rgba(0,0,0,.16), 0 34px 70px -28px rgba(0,0,0,.44);

  /* Status colours are fixed, not derived: they must clear 4.5:1 as text on all
     six pale panels and carry white at 6:1 as a fill. Deriving them from the
     palette would put a red on clay that vanishes into it. */
  --danger:#9b1c14;
  --danger-ink:#ffffff;
  --ok:#1c6b3f;
  --warn:#8a5a00;

  --panel:var(--rail-bg);
  --panel-2:color-mix(in srgb, var(--rail-ink) 5%, var(--rail-bg));

  /* The base alphas the site uses were tuned against a near-black canvas; on the
     mid-tone palettes they collapse into the background. Two consequences, both
     load-bearing: muted canvas text stops at 88%, and NO text under ~20px is
     ever placed on bare --canvas — on forest even pure white only reaches
     4.8:1 there. Small text sits on --canvas-3 (the view header band) or on a
     panel. */
  --ink:var(--on-canvas);
  --ink-2:color-mix(in srgb, var(--on-canvas) 88%, transparent);
  --ink-3:color-mix(in srgb, var(--on-canvas) 62%, transparent);
  --line:color-mix(in srgb, var(--on-canvas) 20%, transparent);
  --line-2:color-mix(in srgb, var(--on-canvas) 34%, transparent);
  --tint:color-mix(in srgb, var(--on-canvas) 8%, transparent);
  --tint-2:color-mix(in srgb, var(--on-canvas) 15%, transparent);
  --field:color-mix(in srgb, var(--on-canvas) 8%, transparent);
  --link:var(--on-canvas);
  --focus:var(--on-canvas);
  --fill:var(--rail-bg);
  --fill-ink:var(--canvas-3);

  color-scheme:light;
}

/* ---- the PANEL context. Pale surface, dark ink, and the accent inverts:
   --canvas as a link colour only reaches 3.6:1 on a pale card, so panels reach
   for --canvas-3 instead. --ink-3 is for icon glyphs, rules and disabled state,
   never for text that has to be read. ---- */
.rail,.mbar,
.card,.dt,.empty,.mediatile,
.drawer-panel,.modal,.login-card,.toast,.themer-pop,
.stat,.qcard,.pcard,.gcard{
  --ink:var(--rail-ink);
  --ink-2:color-mix(in srgb, var(--rail-ink) 80%, transparent);
  --ink-3:color-mix(in srgb, var(--rail-ink) 62%, transparent);
  --line:color-mix(in srgb, var(--rail-ink) 14%, transparent);
  --line-2:color-mix(in srgb, var(--rail-ink) 26%, transparent);
  --tint:color-mix(in srgb, var(--rail-ink) 6%, transparent);
  --tint-2:color-mix(in srgb, var(--rail-ink) 11%, transparent);
  --field:color-mix(in srgb, var(--rail-bg) 55%, #ffffff);
  --link:var(--canvas-3);
  --focus:var(--canvas-3);
  --fill:var(--canvas-3);
  --fill-ink:var(--on-canvas);
  background:var(--panel);
  color:var(--ink);
}

/* ============================================================
   Base
   ============================================================ */
*,*::before,*::after{ box-sizing:border-box }
/* display:flex/grid on .drawer-backdrop, .modal, .themer-pop, .imgpick-bar etc.
   would otherwise beat the UA's [hidden]{display:none} */
[hidden]{ display:none !important }

html{
  -webkit-text-size-adjust:100%;
  color-scheme:light;
  scrollbar-color:var(--line-2) transparent;
}
body{
  margin:0;
  min-height:100dvh;
  background:var(--canvas);
  color:var(--ink);
  font-family:var(--font-body);
  font-size:15px;
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  font-feature-settings:"cv05" 1,"ss01" 1;
  overflow-x:hidden;
  accent-color:var(--canvas-3);
}
img,svg,video{ max-width:100%; display:block }
img{ height:auto }
a{ color:var(--link); text-decoration:none }
a:hover{ text-decoration:underline }
button,input,select,textarea{ font:inherit; color:inherit }
button{ background:none; border:0; padding:0; cursor:pointer }
::selection{ background:var(--canvas-3); color:var(--on-canvas) }
:focus-visible{ outline:2px solid var(--focus); outline-offset:2px }
:focus:not(:focus-visible){ outline:none }

h1,h2,h3,h4,h5{
  font-family:var(--font-display);
  font-weight:700;
  letter-spacing:.02em;
  line-height:1.14;
  margin:0;
  text-wrap:balance;
}
h1{ font-size:1.42rem; letter-spacing:.04em }
h2{ font-size:1.1rem }
h3{ font-size:1rem }
p{ margin:0 0 .85em }
p:last-child{ margin-bottom:0 }
/* <figure> carries a 40px UA side margin, which quietly ruins any grid built
   out of figures — a media tile or a gallery card usually is one */
figure,figcaption,blockquote,dl,dd,ul,ol{ margin:0; padding:0 }
ul,ol{ list-style:none }
fieldset{ margin:0; padding:0; border:0; min-width:0 }
legend{ padding:0 }
table{ border-collapse:collapse }

.mono{ font-family:var(--font-mono); font-size:.82em; letter-spacing:-.01em }
.muted{ color:var(--ink-2) }
.trunc{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0 }
.eyebrow{
  font-family:var(--font-display); font-weight:500; font-size:.62rem;
  letter-spacing:.2em; text-transform:uppercase; color:var(--ink-2);
}
.sr{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

/* icon() returns Material Symbols with viewBox="0 -960 960 960" and 24px stroke
   icons alike; sizing is entirely the box's job */
.ico,.rail-ico,.empty-ico,.banner-ico,.toast-ico,.dt-searchico,.imgpick-ph,.rep-handle,.dt-handle{
  display:inline-grid; place-items:center; flex:none;
}
.ico svg,.rail-ico svg,.empty-ico svg,.banner-ico svg,.toast-ico svg,
.dt-searchico svg,.imgpick-ph svg,.rep-handle svg,.dt-handle svg,.btn svg,
.btn-icon svg,.rail-out svg,.tsw-tick svg,.themer-btn svg{
  display:block; fill:currentColor;
}
.ico{ width:18px; height:18px }
.ico svg{ width:100%; height:100% }
.ico-20{ width:20px; height:20px }
.ico-24{ width:24px; height:24px }

/* ============================================================
   Buttons, badges, spinner
   ============================================================ */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  padding:8px 15px; border:1px solid transparent; border-radius:999px;
  font-family:var(--font-display); font-size:.86rem; font-weight:500;
  letter-spacing:.04em; white-space:nowrap; cursor:pointer;
  transition:background var(--dur) var(--ease), border-color var(--dur) var(--ease),
             filter var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.btn:hover{ text-decoration:none }
.btn:active{ transform:translateY(1px) }
.btn:disabled,.btn[aria-disabled="true"],.btn.is-busy{ opacity:.55; cursor:not-allowed; transform:none }
.btn svg{ width:17px; height:17px }

.btn-primary{ background:var(--fill); color:var(--fill-ink) }
.btn-primary:hover{ filter:brightness(1.08) }
.btn-ghost{ background:var(--tint); color:var(--ink); border-color:var(--line) }
.btn-ghost:hover{ background:var(--tint-2); border-color:var(--line-2) }
.btn-danger{ background:var(--danger); color:var(--danger-ink) }
.btn-danger:hover{ filter:brightness(1.12) }
.btn-quiet{ background:transparent; color:var(--ink-2) }
.btn-quiet:hover{ background:var(--tint); color:var(--ink) }
.btn-sm{ padding:5px 11px; font-size:.78rem; gap:6px }
.btn-sm svg{ width:15px; height:15px }
.btn-icon{
  width:34px; height:34px; padding:0; flex:none; gap:0;
  display:inline-grid; place-items:center; border-radius:9px;
  background:transparent; border:0; color:var(--ink-2);
  transition:background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.btn-icon:hover{ background:var(--tint-2); color:var(--ink) }
.btn-icon.on{ background:var(--tint-2); color:var(--ink) }
.btn-icon.btn-sm{ width:28px; height:28px }
.btn-icon.btn-danger,.btn-icon-danger{ background:transparent; color:var(--ink-2) }
.btn-icon.btn-danger:hover,.btn-icon-danger:hover{
  background:color-mix(in srgb, var(--danger) 15%, transparent); color:var(--danger); filter:none;
}

.spinner{ display:inline-grid; place-items:center; padding:18px }
.spinner-ring,.spin{
  display:block; width:20px; height:20px; border-radius:50%;
  border:2px solid color-mix(in srgb, currentColor 28%, transparent);
  border-top-color:currentColor;
  animation:spin .7s linear infinite;
}
.spin{ width:15px; height:15px }
@keyframes spin{ to{ transform:rotate(360deg) } }

.badge{
  display:inline-flex; align-items:center; gap:5px;
  padding:2px 9px; border-radius:999px;
  background:var(--tint-2); border:1px solid var(--line);
  font-family:var(--font-display); font-weight:500; font-size:.68rem;
  letter-spacing:.1em; text-transform:uppercase; color:var(--ink);
  white-space:nowrap;
}
.badge-ok{ color:var(--ok); border-color:color-mix(in srgb, var(--ok) 34%, transparent); background:color-mix(in srgb, var(--ok) 11%, transparent) }
.badge-warn{ color:var(--warn); border-color:color-mix(in srgb, var(--warn) 34%, transparent); background:color-mix(in srgb, var(--warn) 11%, transparent) }
.badge-danger{ color:var(--danger); border-color:color-mix(in srgb, var(--danger) 34%, transparent); background:color-mix(in srgb, var(--danger) 11%, transparent) }

/* ============================================================
   Shell: rail, mobile bar, working area, view header
   ============================================================ */
.rail{
  position:fixed; inset:0 auto 0 0; width:var(--rail-w); z-index:60;
  display:flex; flex-direction:column;
  background:var(--rail-bg); color:var(--rail-ink);
}
.rail-brand{
  display:flex; align-items:center; gap:11px;
  padding:18px; margin:10px 10px 4px; border-radius:12px;
  background:color-mix(in srgb, var(--canvas) 10%, transparent);
  text-decoration:none; color:var(--rail-ink);
}
.rail-brand:hover{ text-decoration:none }
.rail-brand img{ width:30px; height:auto; flex:none }
.rail-brand b{ display:block; font-family:var(--font-display); font-weight:700; font-size:.94rem; letter-spacing:.02em; line-height:1.15 }
.rail-brand em{
  display:block; font-family:var(--font-display); font-style:normal;
  font-size:.58rem; letter-spacing:.14em; margin-top:2px;
  color:color-mix(in srgb, var(--rail-ink) 78%, transparent);
}

.rail-scroll{ flex:1; overflow-y:auto; padding:10px 10px 16px; scrollbar-width:thin; overscroll-behavior:contain }
.rail-block + .rail-block{ margin-top:0 }
/* The site sets these micro-labels at 52% of the rail ink. At .62rem that is
   about 3:1 on forest and clay, so every muted label on a pale surface here
   bottoms out at 78% — size and tracking still read them as secondary. */
.rail-label{
  margin:16px 0 6px; padding-left:10px;
  font-family:var(--font-display); font-weight:500; font-size:.62rem;
  letter-spacing:.2em; text-transform:uppercase;
  color:color-mix(in srgb, var(--rail-ink) 78%, transparent);
}
.rail-block:first-child .rail-label{ margin-top:4px }
.rail-group{ display:flex; flex-direction:column; gap:1px }
.rail-item{
  display:flex; align-items:center; gap:11px;
  padding:9px 10px; border-radius:9px;
  font-family:var(--font-display); font-size:.9rem; font-weight:500; letter-spacing:.03em;
  line-height:1.3; color:var(--rail-ink); text-decoration:none; text-align:left; width:100%;
  transition:background .16s var(--ease), color .16s var(--ease);
}
.rail-item:hover{ background:color-mix(in srgb, var(--canvas) 12%, transparent); text-decoration:none }
.rail-item > span{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.rail-ico{ width:20px; height:20px; opacity:.7 }
.rail-ico svg{ width:20px; height:20px }
.rail-out{ width:14px; height:14px; opacity:0; flex:none; transition:opacity .16s var(--ease) }
.rail-out svg{ width:14px; height:14px }
.rail-item:hover .rail-out{ opacity:.5 }
/* The site fills the active pill with --canvas; at .9rem that is only 3.6:1 on
   the mid-tone palettes, so the admin drops to --canvas-3 — same component,
   one step deeper, and legible in all six themes. */
.rail-item.on{ background:var(--canvas-3); color:var(--on-canvas) }
.rail-item.on:hover{ background:var(--canvas-3) }
.rail-item.on .rail-ico{ opacity:1 }
/* a count or badge a view drops into the row must not stretch like the label */
.rail-item .rail-n{
  flex:none; font-family:var(--font-mono); font-size:.68rem; letter-spacing:0;
  padding:1px 6px; border-radius:999px;
  background:color-mix(in srgb, var(--rail-ink) 9%, transparent);
  color:color-mix(in srgb, var(--rail-ink) 90%, transparent);
}
.rail-item.on .rail-n{ background:color-mix(in srgb, var(--on-canvas) 18%, transparent); color:var(--on-canvas) }

.rail-foot{
  padding:10px; display:flex; flex-direction:column; gap:4px;
  border-top:1px solid color-mix(in srgb, var(--rail-ink) 14%, transparent);
}
.rail-user{
  display:flex; align-items:center; gap:11px;
  padding:9px 10px; border-radius:10px;
  color:var(--rail-ink); text-decoration:none;
  background:color-mix(in srgb, var(--canvas) 9%, transparent);
}
.rail-user:hover{ background:color-mix(in srgb, var(--canvas) 15%, transparent); text-decoration:none }
.rail-user .rail-ico{ opacity:1 }
.rail-user > span{ flex:1; min-width:0; line-height:1.25 }
.rail-user b{ display:block; font-size:.85rem; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.rail-user em{
  display:block; font-family:var(--font-display); font-style:normal; font-size:.6rem;
  letter-spacing:.14em; text-transform:uppercase;
  color:color-mix(in srgb, var(--rail-ink) 78%, transparent);
}
.rail-signout{
  display:flex; align-items:center; gap:11px; width:100%;
  padding:9px 10px; border-radius:10px; text-align:left;
  font-family:var(--font-display); font-size:.86rem; font-weight:500; letter-spacing:.04em;
  color:var(--rail-ink);
  transition:background .16s var(--ease);
}
.rail-signout:hover{ background:color-mix(in srgb, var(--canvas) 12%, transparent) }
.rail-signout .rail-ico{ opacity:.7 }

/* mobile app bar: hamburger + brand, replaces the rail below 1080px */
.mbar{ display:none }
.mbar-brand{ display:flex; align-items:center; gap:9px; text-decoration:none; color:var(--rail-ink) }
.mbar-brand img{ width:24px; height:auto }
.mbar-brand b{ font-family:var(--font-display); font-weight:700; font-size:1rem; letter-spacing:.04em }
.rail-toggle{
  display:none; width:40px; height:40px; flex:none;
  border:0; border-radius:10px; cursor:pointer;
  background:transparent; color:var(--rail-ink); place-items:center;
}
.rail-toggle:hover{ background:color-mix(in srgb, var(--canvas) 12%, transparent) }
.rail-toggle svg{ width:22px; height:22px; fill:currentColor }
.rail-scrim{ display:none }

.work{
  margin-left:var(--rail-w);
  min-height:100dvh;
  display:flex; flex-direction:column;
  position:relative; isolation:isolate;
}
/* the site's fine technical grid, at a quarter of the strength */
.work::before{
  content:""; position:fixed; inset:0 0 0 var(--rail-w); z-index:-1; pointer-events:none;
  background-image:linear-gradient(color-mix(in srgb, var(--on-canvas) 5%, transparent) 1px, transparent 1px),
                   linear-gradient(90deg, color-mix(in srgb, var(--on-canvas) 5%, transparent) 1px, transparent 1px);
  background-size:72px 72px;
  mask-image:radial-gradient(ellipse 80% 60% at 50% 0%, #000 20%, transparent 76%);
  -webkit-mask-image:radial-gradient(ellipse 80% 60% at 50% 0%, #000 20%, transparent 76%);
}

/* #banner sits above #view inside .work and scrolls away; the view header
   below it is what stays pinned. */
#banner:not(:empty){ padding:var(--gut) var(--gut) 0 }

.view{ display:flex; flex-direction:column; gap:16px; padding-bottom:104px; min-width:0 }
/* the header band runs the full width of the working area, so the gutter lives
   on the siblings rather than on .view itself */
.view > :not(.view-head){ margin-inline:var(--gut); min-width:0 }
.view-head{
  position:sticky; top:0; z-index:40;
  display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  min-height:var(--head-h); padding:11px var(--gut);
  background:var(--canvas-3); color:var(--on-canvas);
  border-bottom:1px solid color-mix(in srgb, var(--on-canvas) 14%, transparent);
}
.view-head > div:first-child{ margin-right:auto; min-width:0 }
.view-title{ font-size:1.26rem; letter-spacing:.04em; overflow:hidden; text-overflow:ellipsis }
.view-sub{ margin:1px 0 0; font-size:.8rem; line-height:1.35; color:var(--ink-2) }
.view-head .btn-ghost{ background:var(--tint); border-color:var(--line) }

.boot,.fatal{ display:grid; place-items:center; padding:64px var(--gut); min-height:60dvh }

.banner{
  display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  padding:12px 16px; border-radius:var(--r);
  background:var(--danger); color:var(--danger-ink);
  box-shadow:var(--shadow);
}
.banner-warn{ background:var(--warn) }
.banner-ico{ width:22px; height:22px; flex:none }
.banner-ico svg{ width:22px; height:22px }
.banner-body{ flex:1; min-width:220px }
.banner-body b{ font-family:var(--font-display); font-weight:500; letter-spacing:.03em; font-size:1rem }
.banner-body p{ margin:2px 0 0; font-size:.86rem }
.banner a:not(.btn){ color:var(--danger-ink); text-decoration:underline }
/* the banner's own action arrives as .btn.btn-danger — red on red, so it flips */
.banner .btn{ background:var(--danger-ink); color:var(--danger); border-color:transparent }
.banner .btn:hover{ filter:brightness(.94) }
.banner-warn .btn{ color:var(--warn) }

/* ============================================================
   Theme picker — the site's, unchanged, down to the localStorage key
   ============================================================ */
.themer{ position:fixed; right:20px; bottom:20px; z-index:120; display:flex; flex-direction:column; align-items:flex-end; gap:10px }
.themer-btn{
  display:inline-flex; align-items:center; gap:8px; cursor:pointer;
  height:44px; padding:0 16px; border:0; border-radius:999px;
  background:var(--rail-bg); color:var(--rail-ink);
  font-family:var(--font-display); font-weight:500; font-size:.82rem; letter-spacing:.06em; text-transform:uppercase;
  box-shadow:0 8px 26px -10px rgba(0,0,0,.55);
  transition:transform .18s var(--ease), box-shadow .18s var(--ease);
}
.themer-btn:hover{ transform:translateY(-1px); box-shadow:0 14px 32px -12px rgba(0,0,0,.6) }
.themer-btn svg{ width:20px; height:20px }
.themer-pop{
  width:236px; padding:12px; border-radius:16px;
  background:var(--rail-bg); color:var(--rail-ink);
  box-shadow:0 20px 50px -16px rgba(0,0,0,.6);
  display:flex; flex-direction:column; gap:2px;
}
.themer-title{
  margin:2px 0 8px; padding-left:8px;
  font-family:var(--font-display); font-weight:500; font-size:.62rem;
  letter-spacing:.2em; text-transform:uppercase;
  color:color-mix(in srgb, var(--rail-ink) 78%, transparent);
}
.tsw{
  display:flex; align-items:center; gap:10px; width:100%; cursor:pointer;
  padding:8px; border:0; border-radius:10px; background:transparent; color:inherit;
  font-family:var(--font-display); font-size:.9rem; font-weight:500; letter-spacing:.03em; text-align:left;
  transition:background .15s var(--ease);
}
.tsw:hover{ background:color-mix(in srgb, var(--canvas) 12%, transparent) }
.tsw-chip{
  width:26px; height:26px; border-radius:8px; flex:none;
  background:linear-gradient(135deg, var(--a) 0 50%, var(--b) 50% 100%);
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.14);
}
.tsw-name{ flex:1 }
.tsw-tick{ width:18px; height:18px; opacity:0 }
.tsw-tick svg{ width:18px; height:18px }
.tsw.on{ background:color-mix(in srgb, var(--canvas) 16%, transparent) }
.tsw.on .tsw-tick{ opacity:.85 }

/* ============================================================
   Cards, notes, fact lists
   ============================================================ */
.cards{ display:grid; gap:14px; grid-template-columns:repeat(auto-fill, minmax(min(100%,300px), 1fr)) }
.cards-tight{ grid-template-columns:repeat(auto-fill, minmax(min(100%,232px), 1fr)) }
.card{ border-radius:var(--r); box-shadow:var(--shadow); overflow:hidden; min-width:0 }
.card-pad{ padding:16px 18px 18px }
.card-title{
  font-family:var(--font-display); font-weight:700; font-size:1rem;
  letter-spacing:.03em; margin:0 0 12px;
}
.card-sub{ font-size:.82rem; color:var(--ink-2); margin:-8px 0 12px }
.card-head{
  display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  padding:13px 16px; border-bottom:1px solid var(--line);
}
.card-head .card-title{ margin:0 }
.card-foot{ padding:12px 16px; border-top:1px solid var(--line); display:flex; align-items:center; gap:10px }

.note{
  padding:10px 12px; border-radius:var(--r-sm); margin:0 0 12px;
  background:var(--tint-2); color:var(--ink); font-size:.86rem;
  border-left:3px solid var(--line-2);
}
.note-danger{
  background:color-mix(in srgb, var(--danger) 12%, transparent);
  border-left-color:var(--danger); color:var(--danger); font-weight:500;
}
.note-warn{ background:color-mix(in srgb, var(--warn) 12%, transparent); border-left-color:var(--warn); color:var(--warn) }
.note-ok{ background:color-mix(in srgb, var(--ok) 12%, transparent); border-left-color:var(--ok); color:var(--ok) }

.facts,.kv{ display:grid; grid-template-columns:auto minmax(0,1fr); gap:8px 18px; align-items:baseline; font-size:.87rem }
.facts dt,.kv dt{
  font-family:var(--font-display); font-weight:500; font-size:.66rem;
  letter-spacing:.14em; text-transform:uppercase; color:var(--ink-2);
}
.facts dd,.kv dd{ margin:0; overflow-wrap:anywhere }
.kv dd{ font-family:var(--font-mono); font-size:.8rem }

/* ============================================================
   dataTable — .dt is the surface, sticky header, zebra-free, row hover
   ============================================================ */
.dt{ border-radius:var(--r); box-shadow:var(--shadow); overflow:hidden; min-width:0 }
.dt-bar{
  display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  padding:11px 14px; border-bottom:1px solid var(--line);
}
.dt-searchwrap{ position:relative; display:flex; align-items:center; flex:1; min-width:180px; max-width:340px }
.dt-searchico{
  position:absolute; left:11px; width:16px; height:16px;
  color:var(--ink-2); pointer-events:none;
}
.dt-searchico svg{ width:16px; height:16px }
/* qualified past the base input rule further down, which is the same
   specificity and comes later — unqualified, its padding wins and the
   placeholder sits under the magnifier */
.dt-searchwrap .dt-search,
.dt-searchwrap input.input{ padding-left:34px; border-radius:999px }
.dt-count{
  font-family:var(--font-display); font-size:.68rem; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-2); white-space:nowrap;
}
.dt-actions{ display:flex; align-items:center; gap:8px; margin-left:auto; flex-wrap:wrap }
.dt-hint{
  margin:0; padding:8px 14px; font-size:.78rem; color:var(--ink);
  background:color-mix(in srgb, var(--warn) 13%, transparent);
  border-bottom:1px solid var(--line);
}

/* ui.js sets overflow-x:auto inline here. A container with overflow-x:auto
   computes overflow-y to auto too, which would silently break position:sticky
   on <th> against the page scroll — so give the wrapper a real height and let
   the rows scroll inside the panel, header pinned. */
.dt-wrap{
  max-height:calc(100dvh - var(--head-h) - 210px);
  min-height:180px;
  overflow-y:auto;
  scrollbar-width:thin;
  overscroll-behavior:contain;
}
.dt-table{ width:100%; border-collapse:separate; border-spacing:0; font-size:.9rem }
.dt-table th,.dt-table td{ text-align:left; vertical-align:middle; padding:9px 12px }
.dt-table thead th{
  position:sticky; top:0; z-index:2;
  background:var(--panel-2);
  border-bottom:1px solid var(--line-2);
  font-family:var(--font-display); font-weight:500; font-size:.66rem;
  letter-spacing:.16em; text-transform:uppercase; color:var(--ink);
  white-space:nowrap;
}
.dt-table thead th.is-sorted{ color:var(--ink); background:var(--tint-2) }
.dt-table tbody td{ border-bottom:1px solid var(--line) }
.dt-table tbody tr:last-child td{ border-bottom:0 }
.dt-row{ transition:background .12s var(--ease) }
.dt-row:hover,.dt-row:focus-within{ background:var(--tint) }
.dt-row[tabindex]{ cursor:pointer }
.dt-row:focus-visible{ outline:2px solid var(--focus); outline-offset:-2px }
.dt-row.is-dragging{ opacity:.45 }
.dt-row.is-over-before td{ box-shadow:inset 0 2px 0 0 var(--fill) }
.dt-row.is-over-after td{ box-shadow:inset 0 -2px 0 0 var(--fill) }
.dt-table td[align="right"],.dt-table th[align="right"]{ text-align:right }
.dt-table .num,.dt-table .col-num{ text-align:right; font-variant-numeric:tabular-nums; font-family:var(--font-mono); font-size:.8rem; color:var(--ink-2) }

.dt-sort{
  display:inline-flex; align-items:center; gap:5px; cursor:pointer;
  font:inherit; letter-spacing:inherit; text-transform:inherit; color:inherit; text-align:left;
}
.dt-sort:hover{ color:var(--ink) }
.dt-arrow{ width:13px; height:13px; display:inline-grid; place-items:center; opacity:0; transition:opacity .15s var(--ease), transform .15s var(--ease) }
.dt-arrow svg{ width:13px; height:13px; fill:currentColor; display:block }
.dt-sort:hover .dt-arrow{ opacity:.5 }
.dt-arrow.on,th.is-sorted .dt-arrow{ opacity:1 }
th[aria-sort="descending"] .dt-arrow{ transform:rotate(180deg) }

.dt-th-handle{ width:36px; padding-left:10px !important; padding-right:0 !important }
.dt-handle{
  width:24px; height:28px; cursor:grab; color:var(--ink-3); opacity:.55;
  transition:opacity .15s var(--ease), color .15s var(--ease); touch-action:none;
}
.dt-handle:active{ cursor:grabbing }
.dt-handle svg{ width:16px; height:16px }
.dt-row:hover .dt-handle,.dt-row:focus-within .dt-handle{ opacity:1; color:var(--ink-2) }
.dt-handle.is-off{ opacity:.25; cursor:not-allowed }
.dt-norows{ padding:26px 16px; text-align:center; color:var(--ink-2); font-size:.88rem }
.dt-emptyhost{ padding:0 }

/* view-supplied cells */
.row-actions{ display:inline-flex; align-items:center; gap:4px; justify-content:flex-end }
@media (hover:hover){
  .row-actions{ opacity:0; transition:opacity .14s var(--ease) }
  tr:hover .row-actions,tr:focus-within .row-actions,
  .pcard:hover .row-actions,.pcard:focus-within .row-actions{ opacity:1 }
}
.cell-title{ font-weight:600; line-height:1.35 }
.cell-sub{ font-size:.79rem; color:var(--ink-2); line-height:1.35; margin-top:1px }
.cell-clamp{ display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden }
.thumb{
  width:44px; height:44px; border-radius:8px; object-fit:cover;
  background:var(--tint-2); border:1px solid var(--line);
}
.thumb-empty{ display:grid; place-items:center; color:var(--ink-3) }
.thumb-empty svg{ width:18px; height:18px; fill:currentColor }

/* ============================================================
   Drawer — ui.js positions the backdrop and the panel inline
   ============================================================ */
.drawer-backdrop{
  background:rgba(0,0,0,.42);
  animation:fade-in .2s var(--ease) both;
}
.drawer-panel{
  box-shadow:var(--shadow-lg);
  animation:drawer-in .3s var(--ease) both;
}
@keyframes fade-in{ from{ opacity:0 } to{ opacity:1 } }
@keyframes drawer-in{ from{ transform:translateX(100%) } to{ transform:none } }
.drawer-head{
  flex:none; display:flex; align-items:center; gap:12px;
  padding:14px 18px; border-bottom:1px solid var(--line);
}
.drawer-titles{ flex:1; min-width:0 }
.drawer-title{ font-family:var(--font-display); font-weight:700; font-size:1.06rem; letter-spacing:.03em }
.drawer-sub{
  margin:2px 0 0; font-family:var(--font-display); font-weight:500; font-size:.62rem;
  letter-spacing:.18em; text-transform:uppercase; color:var(--ink-2);
}
.drawer-body{ padding:18px; scrollbar-width:thin; overscroll-behavior:contain }
.drawer-actions{
  flex:none; display:flex; align-items:center; justify-content:flex-end; gap:10px;
  padding:12px 18px; border-top:1px solid var(--line); background:var(--panel);
}
.drawer-actions > .btn-danger:first-child,
.drawer-actions > .btn-quiet:first-child{ margin-right:auto }

/* ============================================================
   Modal — .modal is the panel, .modal-backdrop the fixed scrim
   ============================================================ */
.modal-backdrop{
  background:rgba(0,0,0,.48); padding:20px;
  animation:fade-in .2s var(--ease) both;
}
.modal{
  position:relative; width:min(560px, 100%); max-height:calc(100dvh - 40px);
  display:flex; flex-direction:column;
  border-radius:var(--r-lg); box-shadow:var(--shadow-lg);
  animation:modal-in .24s var(--ease) both;
}
.modal-sm{ width:min(420px, 100%) }
.modal-md{ width:min(560px, 100%) }
.modal-lg{ width:min(880px, 100%) }
@keyframes modal-in{ from{ opacity:0; transform:translateY(10px) scale(.985) } to{ opacity:1; transform:none } }
.modal-head{ display:flex; align-items:center; gap:12px; padding:16px 20px 12px }
.modal-title{ font-family:var(--font-display); font-weight:700; font-size:1.1rem; letter-spacing:.03em; flex:1; min-width:0 }
.modal-body{ padding:0 20px 4px; overflow-y:auto; scrollbar-width:thin }
.modal-body > p{ color:var(--ink-2) }
.modal-actions{ display:flex; align-items:center; justify-content:flex-end; gap:10px; padding:16px 20px 18px }
.modal-danger .modal-head::before{
  content:""; width:10px; height:10px; border-radius:50%; flex:none;
  background:var(--danger); box-shadow:0 0 0 5px color-mix(in srgb, var(--danger) 18%, transparent);
  margin-right:2px;
}
.modal-danger .modal-title{ color:var(--danger) }

/* ============================================================
   Toasts — ui.js owns the stack's geometry; this is the skin
   ============================================================ */
.toast{
  display:flex; align-items:flex-start; gap:10px;
  padding:11px 14px; border-radius:var(--r-sm);
  border-left:3px solid var(--ink-3);
  box-shadow:var(--shadow-lg);
  font-size:.88rem; line-height:1.45;
  animation:toast-in .26s var(--ease) both;
}
.toast-ico{ width:17px; height:17px; margin-top:1px; flex:none }
.toast-ico svg{ width:17px; height:17px }
.toast-msg{ flex:1; min-width:0; overflow-wrap:anywhere }
.toast-success{ border-left-color:var(--ok) }
.toast-success .toast-ico{ color:var(--ok) }
.toast-error{ border-left-color:var(--danger) }
.toast-error .toast-ico{ color:var(--danger) }
.toast-warn{ border-left-color:var(--warn) }
.toast-warn .toast-ico{ color:var(--warn) }
.toast-info{ border-left-color:var(--fill) }
.toast-info .toast-ico{ color:var(--fill) }
.toast .btn-icon{ width:24px; height:24px; margin:-2px -4px 0 2px }
.toast-out{ animation:toast-out .2s var(--ease) both }
@keyframes toast-in{ from{ opacity:0; transform:translateY(10px) scale(.98) } to{ opacity:1; transform:none } }
@keyframes toast-out{ to{ opacity:0; transform:translateY(6px) scale(.98) } }

/* ============================================================
   Forms
   ============================================================ */
.form{ display:flex; flex-direction:column; gap:15px; min-width:0 }
.f-field{ display:flex; flex-direction:column; gap:6px; min-width:0 }
.f-label{
  display:flex; align-items:center; gap:5px;
  font-family:var(--font-display); font-weight:500; font-size:.68rem;
  letter-spacing:.16em; text-transform:uppercase; color:var(--ink-2);
}
.f-req{ color:var(--danger); font-style:normal; font-size:.8rem; line-height:1 }
.f-help{ margin:0; font-size:.78rem; color:var(--ink-2); line-height:1.45 }
.f-error{ margin:0; font-size:.79rem; color:var(--danger); font-weight:500 }
.f-readonly .input,.f-readonly .input:hover{ background:var(--tint); color:var(--ink-2) }
.has-error .input,.has-error .input-area,.has-error .input-select{ border-color:var(--danger) }
.form-row,.row2{ display:grid; gap:15px; grid-template-columns:repeat(2, minmax(0,1fr)) }
.row3{ display:grid; gap:15px; grid-template-columns:repeat(3, minmax(0,1fr)) }

/* :not([type]) is in the list because <input> with no type attribute is not
   matched by input[type="text"], and a hyperscript helper often omits it */
input:not([type]),
input[type="text"],input[type="url"],input[type="number"],input[type="date"],
input[type="email"],input[type="password"],input[type="search"],input[type="tel"],
textarea,select,.input,.input-area,.input-select{
  width:100%; min-width:0;
  padding:9px 12px;
  background:var(--field); color:var(--ink);
  border:1px solid var(--line-2); border-radius:var(--r-sm);
  font-family:var(--font-body); font-size:.92rem; line-height:1.5;
  transition:border-color .15s var(--ease), background .15s var(--ease);
}
textarea,.input-area{ min-height:96px; resize:vertical; line-height:1.6 }
input:hover,textarea:hover,select:hover{ border-color:var(--ink-3) }
input:focus-visible,textarea:focus-visible,select:focus-visible{
  outline:2px solid var(--focus); outline-offset:1px; border-color:transparent;
}
input:disabled,textarea:disabled,select:disabled,.is-busy input,.is-busy textarea,.is-busy select{
  opacity:.55; cursor:not-allowed;
}
input[readonly]{ background:var(--tint); color:var(--ink-2) }
input[aria-invalid="true"]{ border-color:var(--danger) }
/* Firefox dims placeholders on top of the colour; 80% of the ink is as light as
   a placeholder can go and still clear 4.5:1 on the pale panels. */
::placeholder{ color:color-mix(in srgb, var(--ink) 80%, transparent); opacity:1 }
input[type="number"],.input-mono{ font-variant-numeric:tabular-nums }
.input-mono{ font-family:var(--font-mono); font-size:.84rem }
input[type="date"]::-webkit-calendar-picker-indicator{ cursor:pointer; opacity:.6 }
input[type="date"]::-webkit-calendar-picker-indicator:hover{ opacity:1 }
input[type="search"]::-webkit-search-cancel-button{ cursor:pointer }

select,.input-select{
  appearance:none; -webkit-appearance:none;
  padding-right:34px; cursor:pointer;
  /* the field is pale in every theme, so a fixed dark chevron is always legible */
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-opacity='.6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 11px center; background-size:15px;
}
.view-head select,.view-head .input{ background-color:var(--field); border-color:transparent }
.view-head select{
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-opacity='.8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
/* a combo box carries its own datalist arrow in some engines; keep the box plain */
.input-combo{ padding-right:12px; background-image:none }

.check{ display:flex; align-items:flex-start; gap:9px; cursor:pointer; font-size:.9rem }
.check input[type="checkbox"],.check input[type="radio"]{ width:17px; height:17px; margin:2px 0 0; flex:none; cursor:pointer }
.check span{ line-height:1.45 }
.checks{ display:flex; flex-wrap:wrap; gap:8px 18px }
.switch{ display:inline-flex; align-items:center; gap:10px; cursor:pointer; font-size:.9rem }
.switch input{ position:absolute; opacity:0; width:0; height:0 }
.switch i{
  width:38px; height:22px; flex:none; border-radius:999px; position:relative;
  background:var(--tint-2); border:1px solid var(--line-2);
  transition:background .18s var(--ease), border-color .18s var(--ease);
}
.switch i::after{
  content:""; position:absolute; top:2px; left:2px; width:16px; height:16px;
  border-radius:50%; background:var(--panel); box-shadow:0 1px 3px rgba(0,0,0,.35);
  transition:transform .18s var(--ease);
}
.switch input:checked + i{ background:var(--fill); border-color:transparent }
.switch input:checked + i::after{ transform:translateX(16px) }
.switch input:focus-visible + i{ outline:2px solid var(--focus); outline-offset:2px }

/* ---- repeatable rows: strings and links ---- */
.rep{ display:flex; flex-direction:column; gap:7px; align-items:flex-start }
.rep-list{ display:flex; flex-direction:column; gap:7px; width:100% }
.rep-row{ display:flex; align-items:center; gap:7px; min-width:0 }
.rep-row.is-dragging{ opacity:.5 }
.rep-row.is-over-before{ box-shadow:inset 0 2px 0 0 var(--fill) }
.rep-row.is-over-after{ box-shadow:inset 0 -2px 0 0 var(--fill) }
.rep-handle{
  width:22px; height:32px; cursor:grab; color:var(--ink-3); touch-action:none;
}
.rep-handle:active{ cursor:grabbing }
.rep-handle svg{ width:15px; height:15px }
.rep-fields{ flex:1; min-width:0; display:flex; gap:7px; align-items:center }
.rep-fields > *{ min-width:0 }
.rep-kind{ flex:0 1 132px }
.rep-href{ flex:2 1 0 }
.rep-text{ flex:1 1 0 }
.rep-del{ flex:none; width:30px; height:30px }
.rep-del svg{ width:16px; height:16px }
.rep > .btn{ align-self:flex-start }

/* ---- image picker ---- */
.imgpick{ display:grid; grid-template-columns:120px minmax(0,1fr); gap:12px; align-items:start }
.imgpick-thumb{
  position:relative; aspect-ratio:1; border-radius:var(--r-sm); overflow:hidden;
  background:var(--tint); border:1px solid var(--line);
  display:grid; place-items:center; color:var(--ink-3);
  transition:border-color .15s var(--ease), background .15s var(--ease);
}
.imgpick-thumb.is-drop,.imgpick.is-drop .imgpick-thumb{
  border-color:var(--fill); border-style:dashed; background:var(--tint-2);
}
.imgpick-img{ width:100%; height:100%; object-fit:cover; grid-area:1/1 }
.imgpick-ph{ grid-area:1/1; width:28px; height:28px }
.imgpick-ph svg{ width:28px; height:28px }
.imgpick-body{ display:flex; flex-direction:column; gap:8px; min-width:0 }
.imgpick-path{ font-family:var(--font-mono); font-size:.78rem }
.imgpick-actions{ display:flex; align-items:center; gap:7px; flex-wrap:wrap }
.imgpick-status{ margin:0; font-size:.78rem; color:var(--ink-2) }
.imgpick-bar,.bar{ height:4px; border-radius:2px; background:var(--tint-2); overflow:hidden }
.imgpick-bar-fill,.bar > i{ display:block; height:100%; width:0; background:var(--fill); transition:width .2s linear }

/* the browse modal's library grid, and any view that wants the same tiles */
.mediagrid,.mgrid{ display:grid; gap:12px; grid-template-columns:repeat(auto-fill, minmax(min(100%,148px), 1fr)) }
.mediatile,.mtile{
  position:relative; border-radius:var(--r-sm); overflow:hidden; text-align:left;
  border:1px solid var(--line); box-shadow:var(--shadow); cursor:pointer; width:100%;
  transition:transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.mediatile:hover,.mtile:hover{ transform:translateY(-2px); box-shadow:var(--shadow-lg) }
.mediatile img,.mtile img{ width:100%; aspect-ratio:1; object-fit:cover; background:var(--tint-2) }
.mediatile-name,.mtile-name{
  display:block; padding:7px 9px 9px; font-size:.76rem; font-weight:500;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.mtile-meta{ padding:0 9px 9px; margin-top:-6px; font-family:var(--font-mono); font-size:.68rem; color:var(--ink-2) }
.mediatile.on,.mtile.on,.mediatile[aria-selected="true"]{ outline:2px solid var(--fill); outline-offset:-2px }
.mtile-flag{
  position:absolute; top:6px; left:6px; padding:1px 7px; border-radius:999px;
  background:var(--panel); color:var(--ink); box-shadow:var(--shadow);
  font-family:var(--font-display); font-size:.6rem; letter-spacing:.1em; text-transform:uppercase;
}

.dropzone{
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:8px;
  padding:34px 22px; text-align:center; cursor:pointer;
  border:1.5px dashed var(--line-2); border-radius:var(--r);
  background:var(--tint); color:var(--ink-2);
  transition:border-color .15s var(--ease), background .15s var(--ease);
}
.dropzone:hover{ border-color:var(--ink-3) }
.dropzone.is-drop,.dropzone.over{ border-color:var(--fill); background:var(--tint-2) }
.dropzone b{ font-family:var(--font-display); font-weight:500; font-size:1rem; letter-spacing:.03em; color:var(--ink) }
.dropzone span{ font-size:.82rem }
.dropzone svg{ width:30px; height:30px; fill:currentColor; color:var(--ink-3) }
.upload-row{ display:grid; grid-template-columns:1fr auto; gap:4px 10px; align-items:center; font-size:.82rem }
.upload-row .bar{ grid-column:1 / -1 }

/* ============================================================
   Empty state, skeleton
   ============================================================ */
.empty{
  display:flex; flex-direction:column; align-items:center; gap:10px;
  padding:56px 24px; text-align:center; border-radius:var(--r);
}
.empty-ico{
  width:52px; height:52px; border-radius:50%;
  background:var(--tint-2); color:var(--ink-3); margin-bottom:2px;
}
.empty-ico svg{ width:24px; height:24px }
.empty-title{ font-family:var(--font-display); font-weight:700; font-size:1.05rem; letter-spacing:.03em }
.empty-body{ margin:0; max-width:46ch; font-size:.88rem; color:var(--ink-2) }
.empty .btn{ margin-top:6px }
.dt .empty,.dt-emptyhost .empty{ box-shadow:none; border-radius:0 }

.skel{ display:flex; flex-direction:column; gap:10px; padding:16px }
.skel-row{
  height:38px; border-radius:var(--r-sm);
  background:linear-gradient(90deg, var(--tint) 25%, var(--tint-2) 37%, var(--tint) 63%);
  background-size:400% 100%;
  animation:skel 1.4s ease infinite;
}
.skel-row:nth-child(2n){ opacity:.85 }
@keyframes skel{ from{ background-position:100% 0 } to{ background-position:0 0 } }

/* ============================================================
   Login
   ============================================================ */
.login{
  min-height:100dvh; display:grid; place-items:center;
  padding:24px; background:var(--canvas);
  position:relative; isolation:isolate;
}
.login::before{
  content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
  background-image:linear-gradient(color-mix(in srgb, var(--on-canvas) 6%, transparent) 1px, transparent 1px),
                   linear-gradient(90deg, color-mix(in srgb, var(--on-canvas) 6%, transparent) 1px, transparent 1px);
  background-size:72px 72px;
  mask-image:radial-gradient(ellipse 70% 60% at 50% 40%, #000 10%, transparent 72%);
  -webkit-mask-image:radial-gradient(ellipse 70% 60% at 50% 40%, #000 10%, transparent 72%);
}
.login-card{
  width:min(410px, 100%); padding:28px 28px 26px;
  border-radius:var(--r-lg); box-shadow:var(--shadow-lg);
  display:flex; flex-direction:column;
}
.login-logo{ width:38px; height:auto; margin-bottom:14px }
.login-title{ font-size:1.24rem; letter-spacing:.04em }
.login-sub{ margin:4px 0 20px; font-size:.86rem; color:var(--ink-2) }
.login-form{ display:flex; flex-direction:column; gap:13px }
.login-form .f-label,.login-form label{ margin-bottom:-6px }
.login-form .btn{ width:100%; padding:11px 16px; font-size:.92rem; margin-top:4px }
.login-error,.login-form .f-error{
  display:flex; align-items:flex-start; gap:9px; margin:0;
  padding:10px 12px; border-radius:var(--r-sm);
  background:color-mix(in srgb, var(--danger) 12%, transparent);
  border:1px solid color-mix(in srgb, var(--danger) 40%, transparent);
  color:var(--danger); font-size:.85rem; font-weight:500; line-height:1.45;
}
.login-foot{ margin:16px 0 0; font-size:.76rem; color:var(--ink-2); text-align:center }
.account-form{ max-width:420px }

/* ============================================================
   Extras for the views — same tokens, nothing here is required
   ============================================================ */
.stats{ display:grid; gap:12px; grid-template-columns:repeat(auto-fit, minmax(min(100%,158px), 1fr)) }
.stat{ border-radius:var(--r); padding:15px 16px; box-shadow:var(--shadow); display:flex; flex-direction:column; gap:4px }
.stat-n{ font-family:var(--font-display); font-weight:700; font-size:1.9rem; letter-spacing:.02em; line-height:1 }
.stat-k{ font-family:var(--font-display); font-weight:500; font-size:.64rem; letter-spacing:.16em; text-transform:uppercase; color:var(--ink-2) }
.stat-sub{ font-size:.78rem; color:var(--ink-2) }

.qcards{ display:grid; gap:12px; grid-template-columns:repeat(auto-fill, minmax(min(100%,232px), 1fr)) }
.qcard{
  display:flex; align-items:center; gap:12px; text-align:left; width:100%;
  padding:14px 15px; border-radius:var(--r); border:1px solid var(--line);
  box-shadow:var(--shadow); cursor:pointer; text-decoration:none;
  transition:transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.qcard:hover{ transform:translateY(-2px); box-shadow:var(--shadow-lg); border-color:var(--line-2); text-decoration:none }
.qcard > .ico{ width:36px; height:36px; border-radius:10px; background:var(--tint-2); color:var(--ink) }
.qcard > .ico svg{ width:20px; height:20px }
.qcard b{ display:block; font-family:var(--font-display); font-weight:500; font-size:.92rem; letter-spacing:.03em }
.qcard span span,.qcard small{ display:block; font-size:.78rem; color:var(--ink-2); line-height:1.35 }

.pcard{
  position:relative; display:flex; flex-direction:column;
  border-radius:var(--r); overflow:hidden; box-shadow:var(--shadow);
  transition:transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.pcard:hover{ transform:translateY(-3px); box-shadow:var(--shadow-lg) }
.pcard-img{ aspect-ratio:4/5; background:var(--tint-2); position:relative; display:grid; place-items:center }
.pcard-img img{ width:100%; height:100%; object-fit:cover }
.pcard-body{ padding:12px 14px 14px; display:flex; flex-direction:column; gap:6px; flex:1 }
.pcard-name{ font-family:var(--font-display); font-weight:700; font-size:.98rem; letter-spacing:.02em; line-height:1.2 }
.pcard-meta{ font-size:.79rem; color:var(--ink-2); line-height:1.45; display:flex; flex-direction:column; gap:1px }
.pcard-links{ display:flex; flex-wrap:wrap; gap:5px; margin-top:auto; padding-top:8px }
.pcard-links a,.pcard-links span{ width:26px; height:26px; display:grid; place-items:center; border-radius:7px; background:var(--tint-2); color:var(--ink) }
.pcard-links svg{ width:14px; height:14px; fill:currentColor }
.pcard-sec,.gcard-badge{
  position:absolute; padding:2px 8px; border-radius:999px; max-width:calc(100% - 16px);
  background:var(--panel); color:var(--ink); box-shadow:var(--shadow);
  font-family:var(--font-display); font-size:.6rem; letter-spacing:.1em; text-transform:uppercase;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.pcard-sec{ top:8px; left:8px }
.card-actions{ position:absolute; top:8px; right:8px; z-index:2; display:flex; gap:4px }
.card-actions .btn-icon{ background:var(--panel); box-shadow:var(--shadow); width:30px; height:30px }
@media (hover:hover){
  .pcard .card-actions,.mediatile .card-actions,.mtile .card-actions,.gcard .card-actions{ opacity:0; transition:opacity .15s var(--ease) }
  .pcard:hover .card-actions,.pcard:focus-within .card-actions,
  .mediatile:hover .card-actions,.mediatile:focus-within .card-actions,
  .mtile:hover .card-actions,.mtile:focus-within .card-actions,
  .gcard:hover .card-actions,.gcard:focus-within .card-actions{ opacity:1 }
}

.gcards{ display:grid; gap:12px; grid-template-columns:repeat(auto-fill, minmax(min(100%,176px), 1fr)) }
.gcard{ position:relative; border-radius:var(--r-sm); overflow:hidden; box-shadow:var(--shadow); border:1px solid var(--line) }
.gcard img{ width:100%; aspect-ratio:4/3; object-fit:cover; background:var(--tint-2) }
.gcard-badge{ left:7px; bottom:7px }
/* top-left: bottom-right would collide with a long album name and top-right
   belongs to .card-actions */
.gcard-dim{
  position:absolute; left:7px; top:7px;
  font-family:var(--font-mono); font-size:.64rem;
  padding:1px 6px; border-radius:6px; background:var(--panel); color:var(--ink-2);
}
.gcard.is-dragging{ opacity:.45 }
.gcard.is-over-before{ box-shadow:inset 3px 0 0 0 var(--fill) }

/* A segmented control on its own dark band rather than an underlined row: a tab
   strip usually sits on the bare canvas, and nothing at .84rem survives there.
   Fixed colours, so it reads the same inside a card. */
.tabs{
  display:inline-flex; gap:2px; flex-wrap:wrap; align-self:flex-start;
  max-width:100%; padding:4px; border-radius:999px;
  background:var(--canvas-3); color:var(--on-canvas);
}
.tab{
  padding:6px 14px; border-radius:999px; cursor:pointer;
  font-family:var(--font-display); font-size:.84rem; font-weight:500; letter-spacing:.04em;
  color:color-mix(in srgb, var(--on-canvas) 88%, transparent);
  transition:color .15s var(--ease), background .15s var(--ease);
}
.tab:hover{ background:color-mix(in srgb, var(--on-canvas) 13%, transparent); color:var(--on-canvas) }
.tab.on{ background:var(--rail-bg); color:var(--canvas-3) }
.tab:focus-visible{ outline:2px solid var(--on-canvas); outline-offset:-2px }

.filters{ display:flex; align-items:center; gap:8px; flex-wrap:wrap }
.filters select,.filters input{ width:auto; min-width:150px; padding:6px 11px; font-size:.85rem }
.filters select{ padding-right:32px }
.pager{ display:flex; align-items:center; gap:8px; margin-left:auto; font-size:.82rem; color:var(--ink-2) }

.log{ display:flex; flex-direction:column; font-family:var(--font-mono); font-size:.76rem; line-height:1.6 }
.log-row{ display:grid; grid-template-columns:132px 96px 1fr; gap:10px; padding:6px 16px; border-bottom:1px solid var(--line) }
.log-row:last-child{ border-bottom:0 }
.log-row:hover{ background:var(--tint) }
.log-time{ color:var(--ink-2) }
.log-actor{ font-weight:500; overflow:hidden; text-overflow:ellipsis }
.log-what{ overflow-wrap:anywhere }

/* ============================================================
   Responsive — the rail slides behind the hamburger as the site's does
   ============================================================ */
@media (max-width:1080px){
  .work{ margin-left:0; padding-top:var(--mbar-h) }
  .work::before{ inset:0 }
  .rail{
    top:var(--mbar-h);
    transform:translateX(-100%);
    transition:transform .34s var(--ease);
    box-shadow:0 0 60px rgba(0,0,0,.4);
  }
  .rail.open{ transform:translateX(0) }
  .rail-toggle{ display:grid }
  .mbar{
    display:flex; align-items:center; gap:6px;
    position:fixed; inset:0 0 auto 0; height:var(--mbar-h); z-index:70; padding:0 10px;
    background:var(--rail-bg); color:var(--rail-ink);
    box-shadow:0 2px 14px -4px rgba(0,0,0,.35);
  }
  .rail-scrim{
    display:block; position:fixed; inset:0; z-index:55;
    background:rgba(0,0,0,.45); opacity:0; pointer-events:none;
    transition:opacity .3s var(--ease);
  }
  .rail.open ~ .rail-scrim{ opacity:1; pointer-events:auto }
  .view-head{ top:var(--mbar-h) }
  .themer{ right:14px; bottom:14px }
  /* full-width slide-over: 620px of drawer on a phone is the whole screen anyway */
  .drawer-panel{ width:100% !important }
  .dt-wrap{ max-height:calc(100dvh - var(--mbar-h) - var(--head-h) - 150px) }
}
@media (min-width:1081px){
  .rail{ transform:none }
}
@media (max-width:720px){
  .view-head{ gap:10px }
  .view-title{ font-size:1.12rem }
  .form-row,.row2,.row3{ grid-template-columns:1fr }
  .imgpick{ grid-template-columns:96px minmax(0,1fr) }
  .rep-fields{ flex-wrap:wrap }
  .rep-kind,.rep-href,.rep-text{ flex:1 1 100% }
  .drawer-body,.drawer-head,.drawer-actions{ padding-left:14px; padding-right:14px }
  .log-row{ grid-template-columns:1fr; gap:2px; padding:8px 14px }
  .cards{ grid-template-columns:repeat(auto-fill, minmax(min(100%,180px), 1fr)) }
  /* on a phone the table is horizontal-first; the header un-sticks, which is the
     honest trade for a scroller that has to move on both axes */
  .dt-wrap{ max-height:none }
  .dt-table{ min-width:560px }
  .dt-searchwrap{ max-width:none }
}
@media (max-width:400px){
  .stats{ grid-template-columns:1fr 1fr }
  .qcards{ grid-template-columns:1fr }
  .mediagrid,.mgrid{ grid-template-columns:repeat(auto-fill, minmax(min(100%,116px), 1fr)) }
  .themer-btn span{ display:none }
  .themer-btn{ padding:0 12px }
}

/* ============================================================
   Motion
   ============================================================ */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
    scroll-behavior:auto !important;
  }
  .skel-row{ background:var(--tint-2) }
}

@media print{
  .rail,.mbar,.themer,.view-head,.toast-stack,.drawer-backdrop,.modal-backdrop,.rail-scrim,.dt-bar{ display:none !important }
  .work{ margin-left:0; padding-top:0 }
  body{ background:#fff; color:#000 }
  .card,.dt{ box-shadow:none; border:1px solid #999 }
  .dt-wrap{ max-height:none; overflow:visible }
}
