/* SNU Links — shared styles (ported verbatim from the finalized Launchpad prototype) */
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  background: var(--bg); color: var(--fg);
  -webkit-font-smoothing: antialiased;
}

:root, [data-theme="light"] {
  --bg: #F4F6F9; --card: #FFFFFF; --fg: #0F172A; --muted: #64748B;
  --line: #E6E9EE; --input-bg: #F1F3F6; --row-hover: #F4F6F9;
  --accent: #0B5FAE; --accent-soft: color-mix(in srgb, var(--accent) 11%, transparent);
  --shadow: 0 10px 34px rgba(15,23,42,.08);
}
[data-theme="dark"] {
  --bg: #0A0F1A; --card: #121927; --fg: #EAF0F8; --muted: #8A97AB;
  --line: #1E2737; --input-bg: #0E1521; --row-hover: #161F2E;
  --accent: #4D9BEC; --accent-soft: color-mix(in srgb, var(--accent) 16%, transparent);
  --shadow: 0 10px 34px rgba(0,0,0,.4);
}

.snu-kbd {
  font-family: ui-monospace, "SF Mono", monospace; font-size: 10.5px; color: var(--muted);
  border: 1px solid var(--line); border-radius: 4px; padding: 2px 6px; line-height: 1;
}
.snu-avatar {
  width: 30px; height: 30px; border-radius: 50%; background: var(--accent); color: #fff;
  display: grid; place-items: center; font-size: 11px; font-weight: 700; flex: 0 0 auto;
}

@keyframes snuFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes snuPop { from { opacity: 0; transform: translateY(-6px) scale(.99); } to { opacity: 1; transform: none; } }
@keyframes snuToast { from { opacity: 0; transform: translate(-50%, 12px); } to { opacity: 1; transform: translate(-50%, 0); } }

/* ── shared chrome ── */
.snu-brand { display: flex; align-items: center; gap: 14px; }
.snu-logo {
  width: 34px; height: 34px; border-radius: 9px; background: var(--accent); color: #fff;
  display: grid; place-items: center; font-weight: 700; font-size: 12px; letter-spacing: .3px; flex: 0 0 auto;
}
.snu-brand-t1 { font-size: 15px; font-weight: 700; letter-spacing: .2px; line-height: 1.15; }
.snu-logo-img { height: 46px; width: auto; display: block; flex: 0 0 auto; }
.snu-brand-div { width: 1px; height: 36px; background: var(--line); flex: 0 0 auto; }
.snu-logo-dark { display: none; }
[data-theme="dark"] .snu-logo-light { display: none; }
[data-theme="dark"] .snu-logo-dark { display: block; }
/* .lp-header's bar is dark-navy in both themes now (see .lp-header below),
   so — same as .lp-footer, which always uses config('app.org_logo') — it
   always shows the dark-background logo variant, regardless of theme. */
.lp-header .snu-logo-light { display: none; }
.lp-header .snu-logo-dark { display: block; }
.snu-brand-t2 { font-size: 10px; color: var(--muted); }
.snu-header-actions { display: flex; align-items: center; gap: 10px; }
.snu-iconbtn {
  width: 36px; height: 36px; border-radius: 9px; border: 1px solid var(--line); background: var(--card);
  color: var(--fg); display: grid; place-items: center; cursor: pointer; transition: background .12s, border-color .12s;
}
.snu-iconbtn:hover { background: var(--row-hover); }

.snu-chip {
  display: inline-flex; align-items: center; gap: 7px; padding: 6px 12px; font-size: 12.5px; font-weight: 500;
  border-radius: 999px; border: 1px solid var(--line); background: var(--card); color: var(--fg);
  cursor: pointer; white-space: nowrap; font-family: inherit; transition: background .12s, border-color .12s;
}
.snu-chip:hover { background: var(--row-hover); }
.snu-chip.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.snu-chip-n { font-size: 10.5px; opacity: .8; font-weight: 600; }
.snu-chip.on .snu-chip-n { opacity: .9; }
.snu-dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; }

.snu-star { border: none; background: transparent; cursor: pointer; padding: 3px; display: grid; place-items: center; border-radius: 6px; opacity: .55; transition: opacity .12s, background .12s; }
.snu-star:hover { opacity: 1; background: var(--row-hover); }

.snu-empty { padding: 40px 16px; text-align: center; color: var(--muted); font-size: 13.5px; }
.snu-clear { border: none; background: var(--input-bg); cursor: pointer; color: var(--muted); width: 22px; height: 22px; border-radius: 6px; display: grid; place-items: center; }

/* ════════ Prototype B — Launchpad ════════ */
.lp-root { position: relative; min-height: 100vh; overflow: hidden; display: flex; flex-direction: column; }
.lp-ambient {
  position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(ellipse 55% 45% at 18% -2%, var(--accent-soft), transparent 60%),
    radial-gradient(ellipse 45% 40% at 88% 8%, rgba(124,58,237,.10), transparent 60%);
}
[data-theme="dark"] .lp-ambient {
  background:
    radial-gradient(ellipse 55% 45% at 18% -2%, rgba(77,155,236,.18), transparent 60%),
    radial-gradient(ellipse 45% 40% at 88% 8%, rgba(124,58,237,.16), transparent 60%);
}
.lp-inner { position: relative; padding: 8px 40px 8px; flex: 1 1 auto; }
/* Full-bleed bar, same edge-to-edge width as .lp-footer. In the day theme
   this matches .lp-footer's own (always-dark) background exactly, so the two
   bars read as one system; in the night theme .lp-footer instead matches this
   (see the [data-theme="dark"] .lp-footer rule below) — so whichever
   theme is active, header and footer always share one background. */
.lp-header {
  background: #0A2540;
  border-bottom: 1px solid rgba(255,255,255,.08);
  box-shadow: var(--shadow);
}
[data-theme="dark"] .lp-header {
  background: color-mix(in srgb, var(--accent) 10%, var(--card));
  border-bottom-color: color-mix(in srgb, var(--accent) 22%, var(--line));
}
/* Gutters match .lp-inner's exactly (40px here, 16px below 720px), so the logo
   lines up with the first application tile's column and the profile menu ends
   level with the last — the bar itself stays full-bleed. Deliberately no
   max-width: the 1160px cap this used to carry centred the header content on
   a wide screen while .lp-inner (which has no cap) ran the applications out
   to the viewport edges, so the two never aligned. Keep this in step with
   .lp-inner if its padding ever changes. */
.lp-header-inner {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 16px;
  padding: 14px 40px;
}
.lp-head-l { display: flex; align-items: center; justify-self: start; }
.lp-head-c { justify-self: center; text-align: center; line-height: 1.12; }
/* Hardcoded (not var(--fg)/var(--muted)) since these sit directly on
   .lp-header's always-dark background — same reasoning as .lp-footer-copy's
   own hardcoded color below. */
.lp-head-title { font-size: 16px; font-weight: 700; letter-spacing: .2px; color: #DCE6F2; }
.lp-head-sub { font-size: 10px; color: #8FA6C4; margin-top: 1px; letter-spacing: .3px; }
[data-theme="dark"] .lp-head-title { color: var(--fg); }
[data-theme="dark"] .lp-head-sub { color: var(--muted); }
.lp-header .snu-header-actions { justify-self: end; }
/* corner-radius tweak overrides */
:root[data-twr="sharp"] .lp-tile,:root[data-twr="sharp"] .lp-searchwrap,:root[data-twr="sharp"] .snu-chip,:root[data-twr="sharp"] .snu-iconbtn,:root[data-twr="sharp"] .pub-card,:root[data-twr="sharp"] .pub-card-ic,:root[data-twr="sharp"] .pub-login-btn,:root[data-twr="sharp"] .pub-help,:root[data-twr="sharp"] .login-card,:root[data-twr="sharp"] .login-select,:root[data-twr="sharp"] .login-btn,:root[data-twr="sharp"] .login-persona,:root[data-twr="sharp"] .lp-footer-link { border-radius: 5px !important; }
:root[data-twr="round"] .lp-tile,:root[data-twr="round"] .lp-searchwrap,:root[data-twr="round"] .snu-chip,:root[data-twr="round"] .snu-iconbtn,:root[data-twr="round"] .pub-card,:root[data-twr="round"] .pub-card-ic,:root[data-twr="round"] .pub-login-btn,:root[data-twr="round"] .pub-help,:root[data-twr="round"] .login-card,:root[data-twr="round"] .login-select,:root[data-twr="round"] .login-btn,:root[data-twr="round"] .login-persona,:root[data-twr="round"] .lp-footer-link { border-radius: 18px !important; }
.lp-hero { text-align: center; margin: 2px 0 4px; }
.lp-title { font-size: 18px; font-weight: 600; letter-spacing: -.6px; margin: 0 0 6px; }
.lp-searchwrap {
  width: min(460px, 100%); margin: 0 auto; height: 42px; border-radius: 21px;
  background: var(--card); border: 1px solid var(--line); box-shadow: var(--shadow);
  display: flex; align-items: center; gap: 12px; padding: 0 18px;
}
.lp-searchwrap input { flex: 1; min-width: 0; border: none; outline: none; background: transparent; font-size: 14px; color: var(--fg); font-family: inherit; }
.lp-chips { justify-content: center; padding: 2px 0 11px; }
.lp-body { display: flex; flex-direction: column; gap: 5px; }
.snu-chips { display: flex; gap: 8px; padding: 6px 24px 14px; flex-wrap: wrap; }

.lp-group-head { display: flex; align-items: center; gap: 10px; height: 25px; margin-bottom: 4px; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .7px; color: var(--muted); white-space: nowrap; }
.lp-group-dot { width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto; }
.lp-group-line { flex: 1; height: 1px; background: var(--line); }

.lp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 7px 6px; }
.lp-grid-flat { grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); }
.lp-app { display: flex; flex-direction: column; align-items: center; gap: 4px; cursor: pointer; }
.lp-tile {
  position: relative; width: 44px; height: 44px; border-radius: 13px; color: #fff;
  display: grid; place-items: center;
  background: linear-gradient(150deg, var(--c), color-mix(in srgb, var(--c) 78%, #000 0%));
  box-shadow: 0 8px 18px color-mix(in srgb, var(--c) 38%, transparent); transition: transform .14s;
}
.lp-app:hover .lp-tile { transform: translateY(-3px) scale(1.04); }
.lp-label { font-size: 10.5px; font-weight: 500; text-align: center; line-height: 1.18; max-width: 86px; min-height: 25px; }
.lp-star {
  position: absolute; top: -6px; right: -6px; width: 22px; height: 22px; border-radius: 50%;
  border: none; cursor: pointer; display: grid; place-items: center;
  background: var(--accent); box-shadow: 0 2px 8px rgba(0,0,0,.3);
  opacity: 0; transform: scale(.8); transition: opacity .12s, transform .12s;
}
.lp-app:hover .lp-star { opacity: 1; transform: scale(1); }
.lp-star[data-pinned="true"] { opacity: 1; transform: scale(1); }

/* ── Launchpad footer ── */
.lp-footer {
  position: relative; margin-top: 0; flex: 0 0 auto;
  background: #0A2540; color: #DCE6F2;
  border-top: 1px solid rgba(255,255,255,.08);
}
/* Matches .lp-header's night-theme background (see [data-theme="dark"]
   .lp-header above) so header and footer share one color in this theme too. */
[data-theme="dark"] .lp-footer { background: color-mix(in srgb, var(--accent) 10%, var(--card)); border-top-color: rgba(255,255,255,.06); }
/* Gutters match .lp-inner and .lp-header-inner (40px here, 16px below 720px),
   so the footer logo sits on the same left edge as the header logo and the
   first application tile, and the resource links end level with the profile
   menu on the right. Like the header, deliberately no max-width — the 1160px
   cap this used to carry centred the content while .lp-inner ran the
   applications out to the viewport gutters. Keep all three in step. */
.lp-footer-inner { padding: 10px 40px 0; }
.lp-footer-top {
  display: grid; grid-template-columns: minmax(220px, 300px) 1fr; gap: 10px 48px; align-items: center;
}
.lp-footer-brand { display: flex; flex-direction: column; }
/* The tagline that used to sit under this was removed, so the logo takes the
   whole brand block: ~66px instead of 30px keeps the footer the same overall
   height it had with two stacked children (30 + 6 gap + 2 clamped lines).
   The element is stretched to the column's full width by the flex parent and
   object-fit: contain then centres the artwork inside it, so max-width is
   what keeps it from ever exceeding the column on narrow screens. */
/* align-self: flex-start so the img box shrinks to the artwork's own width
   instead of being stretched across the whole brand column by the flex
   parent's default align-items: stretch. While stretched, object-fit: contain
   centred the artwork in that column, leaving the logo visibly inset from the
   gutter the header logo and the RESOURCES heading both sit on. */
.lp-footer-logo { height: 66px; width: auto; max-width: 100%; object-fit: contain; align-self: flex-start; }

.lp-footer-res-h {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .9px;
  color: #7C93B4; margin: 0 0 8px;
}
.lp-footer-res {
  display: flex; flex-wrap: nowrap; gap: 8px;
}
.lp-footer-link {
  display: flex; align-items: center; gap: 10px; padding: 6px 11px; border-radius: 10px;
  text-decoration: none; color: #DCE6F2; border: 1px solid rgba(255,255,255,.08);
  background: rgba(255,255,255,.03); transition: background .14s, border-color .14s, transform .14s;
  flex: 1 1 0; min-width: 0;
}
.lp-footer-link:hover { background: rgba(255,255,255,.07); border-color: rgba(255,255,255,.18); transform: translateY(-1px); }
.lp-footer-link-ic {
  width: 32px; height: 32px; border-radius: 9px; display: grid; place-items: center; flex: 0 0 auto;
  background: rgba(77,155,236,.16); color: #6FB0F2;
}
.lp-footer-link-name { font-size: 12.5px; font-weight: 600; line-height: 1.2; }

.lp-footer-bar {
  margin-top: 6px; padding: 8px 0; border-top: 1px solid rgba(255,255,255,.08);
  display: flex; align-items: center; justify-content: center; gap: 16px; flex-wrap: wrap;
}
.lp-footer-copy { font-size: 12px; color: #8FA6C4; text-align: center; }
.lp-footer-org-link { color: #DCE6F2; font-weight: 700; text-decoration: none; }
.lp-footer-org-link:hover { text-decoration: underline; }

/* ── Local dev login ── */
.login-stage { position: relative; min-height: 100vh; display: grid; place-items: center; padding: 32px 20px; overflow: hidden; }
.login-card {
  position: relative; z-index: 1; width: min(420px, 100%);
  background: var(--card); border: 1px solid var(--line); border-radius: 22px;
  box-shadow: var(--shadow); padding: 34px 32px 26px; text-align: center;
}
.login-logo { height: 48px; width: auto; margin: 0 auto 16px; display: block; }
.login-logo.snu-logo-dark { display: none; }
[data-theme="dark"] .login-logo.snu-logo-light { display: none; }
[data-theme="dark"] .login-logo.snu-logo-dark { display: block; }
.login-title { font-size: 20px; font-weight: 700; letter-spacing: -.3px; }
.login-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.login-badge {
  display: inline-flex; align-items: center; gap: 6px; margin: 16px 0 4px;
  font-size: 11px; font-weight: 600; color: var(--accent); background: var(--accent-soft);
  padding: 5px 12px; border-radius: 999px;
}
.login-note { font-size: 12.5px; line-height: 1.5; color: var(--muted); margin: 8px 0 22px; }
.login-label { display: block; text-align: left; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .6px; color: var(--muted); margin-bottom: 8px; }
.login-select-wrap { position: relative; }
.login-select {
  width: 100%; height: 46px; padding: 0 40px 0 14px; font-size: 14px; font-weight: 600; font-family: inherit;
  color: var(--fg); background: var(--input-bg); border: 1px solid var(--line); border-radius: 12px;
  -webkit-appearance: none; appearance: none; cursor: pointer;
}
.login-select:focus { outline: none; border-color: var(--accent); }
.login-select-ic { position: absolute; right: 14px; top: 50%; transform: translateY(-50%); color: var(--muted); pointer-events: none; }
.login-btn {
  width: 100%; height: 46px; margin-top: 20px; border: none; border-radius: 12px; cursor: pointer;
  background: var(--accent); color: #fff; font-size: 14px; font-weight: 600; font-family: inherit;
  display: flex; align-items: center; justify-content: center; gap: 8px; transition: filter .14s, transform .1s;
}
.login-btn:hover { filter: brightness(1.07); }
.login-btn:active { transform: translateY(1px); }
.login-error {
  margin-top: 14px; padding: 10px 13px; border-radius: 9px; font-size: 12.5px; font-weight: 500;
  background: #FDECEC; color: #C62828; border: 1px solid #F5C6C6; text-align: left;
}
[data-theme="dark"] .login-error { background: rgba(220,38,38,.14); color: #FCA5A5; border-color: rgba(220,38,38,.35); }

/* Full-width alert banner under the header — see resources/views/errors/
   403.blade.php. Deliberately edge-to-edge (not boxed inside .pub-inner's
   max-width) so it reads as a page-level notice, not just another card. */
.alert-ribbon {
  position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; padding: 8px 20px; background: #DC2626; color: #fff; font-size: 11px; font-weight: 600;
  text-align: center; box-shadow: 0 2px 8px rgba(220,38,38,.25);
  white-space: nowrap; overflow-x: auto;
}
.alert-ribbon svg { flex-shrink: 0; }
.login-msbtn {
  width: 100%; height: 44px; border: 1px solid var(--line); border-radius: 12px; background: var(--card);
  color: var(--fg); font-size: 13px; font-weight: 600; font-family: inherit; cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 9px; text-decoration: none;
  transition: background .12s;
}
.login-msbtn:hover { background: var(--row-hover); }
.login-tag { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); background: var(--input-bg); padding: 2px 6px; border-radius: 5px; }
.login-foot { margin-top: 20px; font-size: 11px; color: var(--muted); display: flex; align-items: center; justify-content: center; gap: 6px; }
.login-actions { position: absolute; top: 18px; right: 18px; z-index: 2; display: flex; align-items: center; gap: 8px; }

/* ── Document tree (Student Policy / Academic Research / Member Policy) ── */
.doc-tree-inner { position: relative; z-index: 1; width: min(980px, 100%); margin: 24px auto 0; }
.doc-tree-crumb { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--muted); margin-bottom: 14px; }
.doc-tree-crumb a { color: var(--muted); text-decoration: none; }
.doc-tree-crumb a:hover { color: var(--fg); }
.doc-tree-crumb-cur { color: var(--fg); font-weight: 600; }
.doc-tree-card { background: var(--card); border: 1px solid var(--line); border-radius: 18px; box-shadow: var(--shadow); overflow: hidden; }
.doc-tree-card-h { padding: 16px 20px; border-bottom: 1px solid var(--line); font-size: 15px; font-weight: 700; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.doc-tree-card-actions { display: flex; gap: 8px; flex: 0 0 auto; }
.doc-tree-btn { display: inline-flex; align-items: center; gap: 7px; height: 32px; padding: 0 13px; border-radius: 9px; border: 1px solid var(--line); background: var(--card); color: var(--fg); font-size: 12.5px; font-weight: 600; font-family: inherit; cursor: pointer; transition: background .12s; }
.doc-tree-btn:hover { background: var(--row-hover); }
.doc-tree-card-b { padding: 10px; }
.doc-tree-card-b--pdf { padding: 0; }
.doc-tree-pdf { height: 82vh; }
.doc-tree-pdf iframe { width: 100%; height: 100%; border: none; display: block; }
.doc-tree-list { list-style: none; margin: 0; padding: 0; }
.doc-tree-list li a {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 10px;
  color: var(--fg); text-decoration: none; font-size: 13.5px; transition: background .12s;
}
.doc-tree-list li a:hover { background: var(--row-hover); }
.doc-tree-list li a span[data-icon] { color: var(--muted); flex-shrink: 0; }
.doc-tree-empty { padding: 10px 12px; font-size: 13px; color: var(--muted); }
.doc-tree-noaccess { padding: 10px 12px; font-size: 13.5px; color: var(--muted); }
/* ── Public landing (logged out) ── */
.pub-stage { position: relative; min-height: 100vh; display: flex; flex-direction: column; overflow: hidden; }
.pub-inner { position: relative; z-index: 1; flex: 1; display: flex; flex-direction: column; width: 100%; max-width: 1180px; margin: 0 auto; padding: 18px 40px 48px; }
.pub-help { display: inline-flex; align-items: center; gap: 7px; height: 36px; padding: 0 14px; border-radius: 9px; border: 1px solid var(--line); background: var(--card); color: var(--fg); font-size: 13px; font-weight: 600; font-family: inherit; cursor: pointer; transition: background .12s; }
.pub-help:hover { background: var(--row-hover); }
.pub-login-btn { display: inline-flex; align-items: center; gap: 8px; height: 36px; padding: 0 16px; border-radius: 9px; border: none; background: var(--accent); color: #fff; font-size: 13px; font-weight: 600; font-family: inherit; cursor: pointer; transition: filter .12s; }
.pub-login-btn:hover { filter: brightness(1.07); }
.pub-intro { font-size: 16px; line-height: 1.65; color: var(--fg); max-width: 720px; margin: 30px 0 32px; text-wrap: pretty; }
.pub-link { color: var(--accent); font-weight: 600; cursor: pointer; border-bottom: 1.5px solid currentColor; padding-bottom: 1px; }
.pub-sec-h { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .7px; color: var(--muted); margin-bottom: 13px; }
.pub-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; max-width: 840px; }
.pub-card {
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 8px;
  padding: 14px 8px; border-radius: 14px; background: var(--card); border: 1px solid var(--line);
  cursor: pointer; font-family: inherit; text-decoration: none; transition: border-color .14s, transform .14s, box-shadow .14s;
}
.pub-card:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: var(--shadow); }
.pub-card-ic { width: 38px; height: 38px; border-radius: 11px; color: #fff; display: grid; place-items: center; flex: 0 0 auto; background: linear-gradient(150deg, var(--c), color-mix(in srgb, var(--c) 76%, #000)); box-shadow: 0 8px 18px color-mix(in srgb, var(--c) 36%, transparent); }
.pub-card-tx { display: flex; flex-direction: column; align-items: center; min-width: 0; }
.pub-card-name { font-size: 12.5px; font-weight: 600; color: var(--fg); }
.pub-card-sub { font-size: 11.5px; color: var(--muted); margin-top: 2px; line-height: 1.35; }
.pub-card-go { font-size: 10.5px; font-weight: 600; color: var(--accent); display: flex; align-items: center; gap: 3px; margin-top: 3px; white-space: nowrap; }

/* split two-column landing */
.pub-split { position: relative; z-index: 1; flex: 1; display: flex; align-items: center; gap: 56px; padding: 30px 0 50px; }
.pub-split-l { flex: 1; }
.pub-eyebrow { font-size: 12px; font-weight: 700; letter-spacing: 1.4px; text-transform: uppercase; color: var(--accent); margin-bottom: 16px; }
.pub-h1 { font-size: 46px; line-height: 1.07; font-weight: 700; letter-spacing: -1.2px; margin: 0 0 16px; color: var(--fg); }
.pub-lead { font-size: 16.5px; line-height: 1.55; color: var(--muted); max-width: 480px; margin: 0; text-wrap: pretty; }
/* Inline "Sign in" link inside .pub-lead. Accent-coloured and underlined
   rather than colour-only, so it still reads as a link against the muted
   paragraph for anyone who can't distinguish the hue. */
.pub-lead-link {
  color: var(--accent); font-weight: 600; text-decoration: underline;
  text-underline-offset: 2px; text-decoration-thickness: 1.5px;
  border-radius: 3px; transition: color .12s;
}
.pub-lead-link:hover { text-decoration-thickness: 2px; }
.pub-lead-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Sized for config('dedicated_apps')'s current single entry (University ERP
   only) rather than the fixed 420px built for the original 3-card row — see
   .pub-panel-list below, which still wraps gracefully if more entries are
   ever added back. */
.pub-split-r { width: 260px; flex: 0 0 auto; }
.pub-panel { background: var(--card); border: 1px solid var(--line); border-radius: 20px; padding: 18px; box-shadow: var(--shadow); }
.pub-panel-h { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .7px; color: var(--muted); margin-bottom: 12px; text-align: center; }
/* auto-fit rather than a hardcoded column count — sizes itself to however
   many config('dedicated_apps') entries actually exist instead of always
   reserving room for 3, which left empty grid tracks now that there's just one. */
.pub-panel-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 8px; }

/* ════════ device preview frame ════════ */
.dev-stage { min-height: 100vh; }
.dev-container { container-type: inline-size; width: 100%; min-height: 100vh; }
.dev-stage.mobile {
  display: flex; justify-content: center; align-items: flex-start; padding: 28px 16px;
  background: repeating-conic-gradient(var(--line) 0% 25%, transparent 0% 50%) 50% / 22px 22px;
}
[data-theme="dark"] .dev-stage.mobile { background: #05080f; }
.dev-stage.mobile .dev-container {
  width: 402px; max-width: 100%; min-height: 0; height: 814px; border-radius: 40px; overflow: hidden auto;
  border: 10px solid #0c1118; box-shadow: 0 30px 80px rgba(0,0,0,.4); background: var(--bg); position: relative;
  scrollbar-width: none;
}
.dev-stage.mobile .dev-container::-webkit-scrollbar { display: none; }
.dev-stage.mobile .login-stage { min-height: 100%; padding-top: 20px; padding-bottom: 20px; }
.dev-toggle {
  position: fixed; bottom: 18px; left: 18px; z-index: 400; display: flex; gap: 3px; padding: 4px;
  background: var(--card); border: 1px solid var(--line); border-radius: 11px; box-shadow: var(--shadow);
}
.dev-toggle button {
  display: flex; align-items: center; gap: 6px; padding: 6px 11px; font-size: 12px; font-weight: 600;
  border: none; border-radius: 8px; cursor: pointer; background: transparent; color: var(--muted); font-family: inherit;
}
.dev-toggle button.on { background: var(--accent); color: #fff; }

/* ── responsive ──
   NOTE: this used to be `@container (max-width: 720px)`, which only ever
   fires inside an ancestor with `container-type` set — the deleted
   Tweaks.jsx device-preview frame (`.dev-container`) was the only element
   that had one. No real page wraps its content in that class, so those
   rules never applied on an actual phone no matter how narrow the
   viewport was. `@media` is what actually reflows the shipped pages. */
@media (max-width: 720px) {
  .snu-hide-sm { display: none !important; }

  /* Header fit. Three things stacked up to push the Login button off the
     right edge on a ~412px phone:
       1. the desktop 40px side padding (80px of an already narrow viewport)
          was only reduced at the 400px breakpoint below, so anything from
          401px up kept all of it;
       2. .lp-head-c is display:none here, but `1fr auto 1fr` still reserves
          a third column, and `1fr` means `minmax(auto, 1fr)` — that `auto`
          minimum stops either side shrinking below its content;
       3. the logo kept its 46px height (154px wide at its 322x96 aspect)
          until 400px.
     Logo + actions therefore demanded ~495px inside 412px, and .snu-header-
     actions being last in flow meant the primary action took the overflow.
     Two columns, tighter padding, and a logo that scales instead of holding
     a fixed width. */
  .lp-header-inner { grid-template-columns: minmax(0, 1fr) auto; gap: 10px; padding: 10px 16px; }
  /* Lets the (flex) logo column actually shrink — without this its
     min-content width still wins and the overflow comes straight back. */
  .lp-head-l { min-width: 0; }
  /* max-height + max-width rather than a fixed height: the image keeps its
     aspect ratio while being free to scale down if the actions cluster ever
     needs the room, so the failure mode is a slightly smaller logo instead
     of a clipped button. */
  .snu-logo-img { height: auto; width: auto; max-height: 38px; max-width: 100%; }
  /* The actions are the primary controls — they hold their size and the
     logo yields, not the other way round. */
  .lp-header .snu-header-actions { gap: 6px; flex: 0 0 auto; }
  .snu-chips { padding: 4px 14px 12px; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .snu-chips::-webkit-scrollbar { display: none; }

  .lp-inner { padding: 18px 16px 32px; }
  .lp-title { font-size: 20px; }
  .lp-chips { flex-wrap: nowrap; overflow-x: auto; justify-content: flex-start; scrollbar-width: none; }
  .lp-chips::-webkit-scrollbar { display: none; }
  .lp-grid, .lp-grid-flat { grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); gap: 16px 4px; }
  .lp-tile { width: 54px; height: 54px; }

  /* Ctrl+K only means anything with a physical keyboard. */
  [data-search-kbd] { display: none !important; }

  /* Touch targets: bump icon buttons/chips up toward the ~40-44px
     minimum comfortable tap size instead of the desktop 36px/30px. */
  .snu-iconbtn { width: 40px; height: 40px; }
  .snu-chip { padding: 8px 14px; }

  /* 16px, not 18px — matches .lp-inner and .lp-header-inner at this width. */
  .lp-footer-inner { padding: 26px 16px 0; }
  .lp-footer-top { grid-template-columns: 1fr; gap: 26px; }
  .lp-footer-res { flex-wrap: wrap; }
  .lp-footer-link { flex: 0 0 calc(50% - 4px); }
  .lp-footer-bar { flex-direction: column; align-items: center; gap: 10px; }

  .pub-inner { padding: 14px 16px 36px; }
  .pub-intro { font-size: 15px; margin: 22px 0 26px; }
  .pub-grid { grid-template-columns: 1fr; max-width: none; }
  .pub-split { flex-direction: column; align-items: stretch; gap: 28px; padding: 24px 0 36px; }
  .pub-split-r { width: 100%; }
  .pub-h1 { font-size: 34px; }
  .pub-lead { font-size: 15px; }

  .doc-tree-crumb { flex-wrap: wrap; row-gap: 4px; }
  .help-modal-overlay { padding: 12px; }

  /* login-back/login-actions are position:absolute in the top corners —
     give the card enough clearance on short/narrow viewports so they
     never sit on top of the logo. */
  .login-stage { padding-top: 76px; }
}

/* Narrow phones: collapse Help to its icon so the actions cluster stays well
   inside the viewport, leaving Login — the primary action — at full size with
   its label. Kept above the 400px block because 412px-class devices (Pixel)
   are exactly where the cluster was running out of room. */
@media (max-width: 440px) {
  .pub-help-label { display: none; }
  /* Square up the button now that it's icon-only — the 14px side padding was
     sized for padding + icon + gap + label. */
  .pub-help { padding: 0 11px; gap: 0; }
}

/* Extra-small phones (~360px and under: SE-class widths, small Android). */
@media (max-width: 400px) {
  /* 16px, not 14px — .lp-inner stays on 16px gutters at this width, and the
     header is meant to line up with the applications at every breakpoint. */
  .lp-header-inner { gap: 8px; padding: 10px 16px; }
  /* max-height, not height — the 720px block switched this image to
     aspect-preserving auto sizing, and a fixed height here would re-pin the
     width and undo it. */
  .snu-logo-img { max-height: 34px; }
  .snu-header-actions { gap: 6px; }

  .pub-eyebrow { font-size: 11px; letter-spacing: 1px; }
  .pub-h1 { font-size: 28px; }
  /* Three columns get too cramped below ~400px — back to a single stacked
     column, same as the pre-redesign layout, just for this width. */
  .pub-panel-list { grid-template-columns: 1fr; }
  .pub-card { flex-direction: row; text-align: left; }
  .pub-card-tx { align-items: flex-start; }

  .login-card { padding: 26px 18px 20px; }
  .doc-tree-card-h { font-size: 14px; padding: 14px 16px; flex-wrap: wrap; }
  .lp-footer-link { flex: 1 1 100%; }
}

/* ════════ Tweaks panel (accent / corners / greeting) ════════ */
.twk-panel{position:fixed;right:16px;bottom:16px;z-index:2147483646;width:280px;
  max-height:calc(100vh - 32px);display:flex;flex-direction:column;
  background:rgba(250,249,247,.78);color:#29261b;
  -webkit-backdrop-filter:blur(24px) saturate(160%);backdrop-filter:blur(24px) saturate(160%);
  border:.5px solid rgba(255,255,255,.6);border-radius:14px;
  box-shadow:0 1px 0 rgba(255,255,255,.5) inset,0 12px 40px rgba(0,0,0,.18);
  font:11.5px/1.4 ui-sans-serif,system-ui,-apple-system,sans-serif;overflow:hidden}
.twk-hd{display:flex;align-items:center;justify-content:space-between;
  padding:10px 8px 10px 14px;cursor:move;user-select:none}
.twk-hd b{font-size:12px;font-weight:600;letter-spacing:.01em}
.twk-x{appearance:none;border:0;background:transparent;color:rgba(41,38,27,.55);
  width:22px;height:22px;border-radius:6px;cursor:pointer;font-size:13px;line-height:1}
.twk-x:hover{background:rgba(0,0,0,.06);color:#29261b}
.twk-body{padding:2px 14px 14px;display:flex;flex-direction:column;gap:10px;
  overflow-y:auto;overflow-x:hidden;min-height:0;
  scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.15) transparent}
.twk-body::-webkit-scrollbar{width:8px}
.twk-body::-webkit-scrollbar-track{background:transparent;margin:2px}
.twk-body::-webkit-scrollbar-thumb{background:rgba(0,0,0,.15);border-radius:4px;
  border:2px solid transparent;background-clip:content-box}
.twk-body::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.25);
  border:2px solid transparent;background-clip:content-box}
.twk-row{display:flex;flex-direction:column;gap:5px}
.twk-row-h{flex-direction:row;align-items:center;justify-content:space-between;gap:10px}
.twk-lbl{display:flex;justify-content:space-between;align-items:baseline;
  color:rgba(41,38,27,.72)}
.twk-lbl>span:first-child{font-weight:500}
.twk-val{color:rgba(41,38,27,.5);font-variant-numeric:tabular-nums}
.twk-sect{font-size:10px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:rgba(41,38,27,.45);padding:10px 0 0}
.twk-sect:first-child{padding-top:0}
.twk-field{appearance:none;box-sizing:border-box;width:100%;min-width:0;height:26px;padding:0 8px;
  border:.5px solid rgba(0,0,0,.1);border-radius:7px;
  background:rgba(255,255,255,.6);color:inherit;font:inherit;outline:none}
.twk-field:focus{border-color:rgba(0,0,0,.25);background:rgba(255,255,255,.85)}
.twk-seg{position:relative;display:flex;padding:2px;border-radius:8px;
  background:rgba(0,0,0,.06);user-select:none}
.twk-seg-thumb{position:absolute;top:2px;bottom:2px;border-radius:6px;
  background:rgba(255,255,255,.9);box-shadow:0 1px 2px rgba(0,0,0,.12);
  transition:left .15s cubic-bezier(.3,.7,.4,1),width .15s}
.twk-seg.dragging .twk-seg-thumb{transition:none}
.twk-seg button{appearance:none;position:relative;z-index:1;flex:1;border:0;
  background:transparent;color:inherit;font:inherit;font-weight:500;min-height:22px;
  border-radius:6px;cursor:pointer;padding:4px 6px;line-height:1.2;
  overflow-wrap:anywhere}
.twk-chips{display:flex;gap:6px}
.twk-chip{position:relative;appearance:none;flex:1;min-width:0;height:46px;
  padding:0;border:0;border-radius:6px;overflow:hidden;cursor:pointer;
  box-shadow:0 0 0 .5px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.06);
  transition:transform .12s cubic-bezier(.3,.7,.4,1),box-shadow .12s}
.twk-chip:hover{transform:translateY(-1px);
  box-shadow:0 0 0 .5px rgba(0,0,0,.18),0 4px 10px rgba(0,0,0,.12)}
.twk-chip[data-on="1"]{box-shadow:0 0 0 1.5px rgba(0,0,0,.85),
  0 2px 6px rgba(0,0,0,.15)}
.twk-chip>span{position:absolute;top:0;bottom:0;right:0;width:34%;
  display:flex;flex-direction:column;box-shadow:-1px 0 0 rgba(0,0,0,.1)}
.twk-chip>span>i{flex:1;box-shadow:0 -1px 0 rgba(0,0,0,.1)}
.twk-chip>span>i:first-child{box-shadow:none}
.twk-chip svg{position:absolute;top:6px;left:6px;width:13px;height:13px;
  filter:drop-shadow(0 1px 1px rgba(0,0,0,.3))}
.dev-toggle .twk-open{color:var(--muted)}
.dev-toggle .twk-open.on{background:var(--accent);color:#fff}

/* ════════ Dropdown menus (Help / Profile) — Blade+vanilla-JS port of the
   React ProfileMenu/HelpMenu components, which used inline styles + JS-driven
   hover. Kept as real CSS here since these dropdowns are now static markup. ════════ */
.snu-dropdown { position: relative; }
.snu-dropdown-toggle {
  display: flex; align-items: center; gap: 9px; padding: 4px 9px 4px 4px;
  border-radius: 999px; border: 1px solid var(--line); background: var(--card);
  cursor: pointer; color: var(--fg); font-family: inherit;
}
.snu-dropdown-menu {
  position: absolute; top: 110%; right: 0; z-index: 120;
  background: var(--card); border: 1px solid var(--line); border-radius: 14px;
  box-shadow: 0 18px 50px rgba(0,0,0,.22); overflow: hidden; animation: snuPop .12s ease;
  /* header.blade.php/help-menu.blade.php set a fixed inline width (e.g.
     220-248px) — this caps it against the viewport instead of overflowing
     off the left edge on narrow phones; max-width isn't set inline, so it
     layers on top of the inline width without needing !important. */
  max-width: calc(100vw - 24px);
}
.snu-dropdown-head { padding: 14px; display: flex; align-items: center; gap: 11px; border-bottom: 1px solid var(--line); }
.snu-dropdown-head-n { font-size: 13.5px; font-weight: 600; }
.snu-dropdown-head-d { font-size: 11.5px; color: var(--muted); }
.snu-dropdown-body { padding: 8px; }
.snu-dropdown-item {
  width: 100%; display: flex; align-items: center; gap: 11px; padding: 9px 10px;
  border-radius: 8px; border: none; background: transparent; cursor: pointer;
  font-size: 13px; font-weight: 500; font-family: inherit; text-align: left;
  color: var(--fg); text-decoration: none; transition: background .12s;
}
.snu-dropdown-item:hover { background: var(--row-hover); }
.snu-dropdown-item svg { color: var(--muted); }
.snu-dropdown-item--danger, .snu-dropdown-item--danger svg { color: #DC2626; }
/* Same [hidden]-vs-author-stylesheet issue as .palette-overlay below: this
   class's display:flex beats the UA default [hidden]{display:none} rule, so
   the Admin link (header.blade.php/launchpad.blade.php's [data-admin-link])
   stayed visible for non-admin users despite having the hidden attribute. */
.snu-dropdown-item[hidden] { display: none; }

/* Command palette overlay. display:flex must live in a stylesheet (not an
   inline style) so the [hidden] attribute's UA display:none can win when set —
   an inline style on the same element would always beat it regardless of the
   hidden attribute. */
.palette-overlay {
  position: fixed; inset: 0; z-index: 200; background: rgba(8,12,20,.5);
  backdrop-filter: blur(4px); display: flex; align-items: flex-start;
  justify-content: center; padding-top: 12vh;
}
.palette-overlay[hidden] { display: none; }

/* Help modals (partials/help-menu.blade.php) — same [hidden]-vs-stylesheet
   reasoning as .palette-overlay above. */
.help-modal-overlay {
  position: fixed; inset: 0; z-index: 250; background: rgba(8,12,20,.5);
  backdrop-filter: blur(4px); display: flex; align-items: center;
  justify-content: center; padding: 24px;
}
.help-modal-overlay[hidden] { display: none; }
.help-modal {
  width: min(560px, 100%); max-height: 80vh; overflow-y: auto;
  background: var(--card); border: 1px solid var(--line); border-radius: 16px;
  box-shadow: 0 24px 70px rgba(0,0,0,.35);
}
.help-modal-h {
  position: sticky; top: 0; display: flex; align-items: center; justify-content: space-between;
  padding: 15px 18px; border-bottom: 1px solid var(--line); background: var(--card);
  font-weight: 600; font-size: 14.5px;
}
.help-modal-h > span { display: flex; align-items: center; gap: 8px; }
.help-modal-body { padding: 4px 20px 18px; font-size: 13px; line-height: 1.55; color: var(--fg); }
.help-modal-body h4 { font-size: 12.5px; margin: 14px 0 6px; }
.help-modal-body ul { margin: 0 0 4px; padding-left: 18px; }
.help-modal-body li { margin-bottom: 4px; }
.help-modal-body li ul { margin-top: 4px; }
.help-modal-body hr { border: none; border-top: 1px solid var(--line); margin: 14px 0; }
.help-modal-body a { color: var(--accent); }

/* Same [hidden]-vs-author-stylesheet issue as .palette-overlay: any element
   whose class sets a non-"none" display (here .snu-clear's display:grid,
   defined earlier in this file) needs an explicit [hidden] override, since
   author-stylesheet rules beat the UA default [hidden]{display:none} rule
   regardless of specificity. */
.snu-clear[hidden] { display: none; }
.snu-chips[hidden] { display: none; }

.snu-toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%); z-index: 300;
  background: var(--fg); color: var(--bg); padding: 11px 18px; border-radius: 12px;
  display: flex; align-items: center; gap: 11px; box-shadow: 0 12px 40px rgba(0,0,0,.3);
  font-size: 13.5px; font-weight: 500;
  max-width: calc(100vw - 32px); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.snu-toast[hidden] { display: none; }

/* ── Admin portal (resources/views/admin/*.blade.php) ── */
.admin-inner { position: relative; z-index: 1; width: min(980px, 100%); margin: 24px auto 40px; }

.admin-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
.admin-card { display: flex; align-items: center; gap: 14px; padding: 18px; border-radius: 16px; background: var(--card); border: 1px solid var(--line); text-decoration: none; color: inherit; transition: border-color .14s, transform .14s, box-shadow .14s; }
.admin-card:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: var(--shadow); }
.admin-card-ic { width: 44px; height: 44px; border-radius: 12px; background: var(--accent-soft); color: var(--accent); display: grid; place-items: center; flex: 0 0 auto; }
.admin-card-tx { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.admin-card-name { font-size: 14.5px; font-weight: 600; color: var(--fg); }
.admin-card-sub { font-size: 11.5px; color: var(--muted); margin-top: 2px; text-transform: capitalize; }
.admin-card-go { color: var(--muted); flex: 0 0 auto; }

.admin-panel { background: var(--card); border: 1px solid var(--line); border-radius: 18px; box-shadow: var(--shadow); margin-bottom: 18px; overflow: hidden; }
.admin-panel-h { display: flex; align-items: center; justify-content: space-between; padding: 15px 20px; border-bottom: 1px solid var(--line); font-size: 15px; font-weight: 700; }
.admin-panel-b { padding: 8px 20px 18px; }

.admin-btn { display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 14px; border-radius: 9px; border: 1px solid var(--line); background: var(--card); color: var(--fg); font-size: 12.5px; font-weight: 600; font-family: inherit; cursor: pointer; transition: background .12s, filter .12s; }
.admin-btn:hover { background: var(--row-hover); }
.admin-btn:disabled, .admin-btn:disabled:hover { opacity: .45; cursor: not-allowed; filter: none; }
.admin-btn--primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.admin-btn--primary:hover { filter: brightness(1.07); background: var(--accent); }
.admin-btn--danger { color: #DC2626; border-color: color-mix(in srgb, #DC2626 30%, var(--line)); }
.admin-btn--danger:hover { background: color-mix(in srgb, #DC2626 10%, transparent); }
.admin-btn--sm { height: 28px; padding: 0 10px; font-size: 11.5px; }

.admin-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.admin-table th { text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); font-weight: 700; padding: 8px 10px; border-bottom: 1px solid var(--line); }
.admin-table td { padding: 9px 10px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.admin-table tr:last-child td { border-bottom: none; }
.admin-table td.admin-table-actions { white-space: nowrap; text-align: right; }
.admin-table-actions .admin-btn { margin-left: 6px; }
.admin-empty { padding: 18px 10px; color: var(--muted); font-size: 13px; text-align: center; }
.admin-swatch { display: inline-block; width: 14px; height: 14px; border-radius: 4px; vertical-align: middle; margin-right: 6px; border: 1px solid var(--line); }

.admin-modal-overlay { position: fixed; inset: 0; z-index: 260; background: rgba(8,12,20,.5); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; padding: 24px; }
.admin-modal-overlay[hidden] { display: none; }
/* overflow:hidden (not auto) + border-radius live on this outer box only —
   putting the scrollbar here instead squares off the corners, since the
   native scrollbar track renders flush to the element's edge regardless of
   border-radius. The header/footer stay fixed and only .admin-modal-b
   scrolls internally, which also keeps Cancel/Save always visible instead
   of scrolling away with long forms. */
.admin-modal {
  width: min(480px, 100%); max-height: 86vh; overflow: hidden;
  background: var(--card); border: 1px solid var(--line); border-radius: 16px; box-shadow: 0 24px 70px rgba(0,0,0,.35);
  display: flex; flex-direction: column;
}
/* The Category/Application modals wrap .admin-modal-b + .admin-modal-f in a
   <form> — that form, not those two elements, is .admin-modal's actual
   second flex item, so it needs the flex-column treatment too, or its
   children's own flex/min-height rules below never take effect at all
   (the confirm-delete modal has no <form> wrapper, so this rule doesn't
   touch it — its .admin-modal-b/-f are already direct flex children). */
.admin-modal > form { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.admin-modal-h { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; padding: 15px 18px; border-bottom: 1px solid var(--line); background: var(--card); font-weight: 600; font-size: 14.5px; }
.admin-modal-b {
  /* min-height:0 overrides a flex item's default min-height:auto, which
     otherwise forces it to grow to fit all its content regardless of
     max-height — without this, overflow-y:auto never actually engages, the
     footer gets pushed past the outer .admin-modal's overflow:hidden clip,
     and long forms (Edit Application) lose fields entirely with no
     scrollbar ever appearing. */
  flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 16px 18px 18px;
  scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--muted) 55%, transparent) transparent;
}
.admin-modal-b::-webkit-scrollbar { width: 8px; }
.admin-modal-b::-webkit-scrollbar-track { background: transparent; margin: 4px; }
.admin-modal-b::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--muted) 55%, transparent); border-radius: 4px; }
.admin-modal-b::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--muted) 80%, transparent); }
.admin-modal-b::-webkit-scrollbar { width: 8px; }
.admin-modal-b::-webkit-scrollbar-track { background: transparent; margin: 4px; }
.admin-modal-b::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--muted) 55%, transparent); border-radius: 4px; }
.admin-modal-b::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--muted) 80%, transparent); }
.admin-modal-f { flex: 0 0 auto; display: flex; justify-content: flex-end; gap: 8px; padding: 12px 18px; border-top: 1px solid var(--line); }

.admin-modal--view { width: min(900px, 96vw); }
.admin-modal--view .admin-modal-b { padding: 0; }
.admin-view-pdf { height: 78vh; }
.admin-view-pdf iframe { width: 100%; height: 100%; border: none; display: block; }
.admin-view-fallback { height: 40vh; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px; }
.admin-view-fallback[hidden] { display: none; }
.admin-view-fallback p { color: var(--muted); font-size: 13.5px; margin: 0; }

.admin-search {
  display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 12px;
  border-radius: 9px; border: 1px solid var(--line); background: var(--input-bg); margin-bottom: 12px;
}
.admin-search span[data-icon] { color: var(--muted); flex-shrink: 0; }
.admin-search input { flex: 1; min-width: 0; border: none; outline: none; background: transparent; font-size: 13px; color: var(--fg); font-family: inherit; }

.admin-field { margin-bottom: 12px; }
.admin-field label { display: block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); margin-bottom: 6px; }
.admin-required { color: #DC2626; }
.admin-field input[type="text"], .admin-field input[type="url"], .admin-field select, .admin-field textarea {
  width: 100%; height: 38px; padding: 0 12px; border-radius: 9px; border: 1px solid var(--line);
  background: var(--input-bg); color: var(--fg); font-size: 13px; font-family: inherit;
}
.admin-field textarea { height: auto; padding: 8px 12px; min-height: 64px; resize: vertical; }
.admin-field-checks { display: flex; flex-wrap: wrap; gap: 10px; }
.admin-field-check { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; }
.admin-field-hint { font-size: 11px; color: var(--muted); margin-top: 4px; }
.admin-error { color: #DC2626; font-size: 11.5px; margin-top: 4px; }

/* Per-field inline validation message, shown directly under the offending
   input instead of (or alongside) the modal's single [data-form-error]
   banner — see admin-snu-links.js/admin-document-tree.js's showFieldError(). */
.admin-field-error { display: none; color: #DC2626; font-size: 11.5px; margin-top: 4px; }
.admin-field.has-error .admin-field-error { display: block; }
.admin-field.has-error input[type="text"],
.admin-field.has-error input[type="file"],
.admin-field.has-error select,
.admin-field.has-error textarea,
.admin-field.has-error .admin-combo-trigger {
  border-color: #DC2626;
}

.admin-modal--confirm .admin-modal-h--danger { border-bottom-color: color-mix(in srgb, #DC2626 25%, var(--line)); }
.admin-modal-h-title { display: flex; align-items: center; gap: 10px; }
.admin-modal-h-actions { display: flex; align-items: center; gap: 10px; }
.admin-confirm-icon {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 30px; height: 30px; border-radius: 50%; background: #FDECEC; color: #DC2626;
}
[data-theme="dark"] .admin-confirm-icon { background: rgba(220,38,38,.16); color: #FCA5A5; }
.admin-confirm-message { font-size: 13.5px; line-height: 1.55; color: var(--fg); margin: 0; }
.admin-confirm-list {
  list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px;
  max-height: 160px; overflow-y: auto;
}
.admin-confirm-list[hidden] { display: none; }
[data-confirm-type-wrap] { margin-top: 18px; margin-bottom: 0; }
/* "Type demo to confirm" reads as a sentence, not a field label — same
   non-uppercase override + name chip as the delete-category modal's
   equivalent (.delcat-zone[data-delcat-zone="all"] label / code). */
.admin-confirm-type label { font-size: 13px; font-weight: 400; text-transform: none; letter-spacing: normal; color: var(--muted); }
.admin-confirm-type code {
  font-family: ui-monospace, "SF Mono", monospace; font-size: 12.5px; font-weight: 600;
  color: var(--accent); background: var(--accent-soft); padding: 2px 7px; border-radius: 5px;
}
.admin-confirm-list li {
  background: var(--accent-soft); color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 25%, var(--line));
  border-radius: 999px; padding: 4px 12px; font-size: 12px; font-weight: 600; white-space: nowrap;
}
.admin-btn--danger-solid { background: #DC2626; border-color: #DC2626; color: #fff; }
.admin-btn--danger-solid:hover { filter: brightness(1.08); background: #DC2626; }
[data-theme="dark"] .admin-btn--danger-solid { background: #EF4444; border-color: #EF4444; }

/* Document-tree row action buttons (admin-document-tree.js) — one filled
   color per action instead of a plain bordered box, so the icon reads at a
   glance without needing the tooltip. */
.admin-btn--folder-solid { background: var(--accent); border-color: var(--accent); color: #fff; }
.admin-btn--folder-solid:hover { filter: brightness(1.08); background: var(--accent); }
.admin-btn--upload-solid { background: #0D9488; border-color: #0D9488; color: #fff; }
.admin-btn--upload-solid:hover { filter: brightness(1.08); background: #0D9488; }
.admin-btn--view-solid { background: #4F46E5; border-color: #4F46E5; color: #fff; }
.admin-btn--view-solid:hover { filter: brightness(1.08); background: #4F46E5; }
.admin-btn--edit-solid { background: #D97706; border-color: #D97706; color: #fff; }
.admin-btn--edit-solid:hover { filter: brightness(1.08); background: #D97706; }

/* Delete-category modal (admin-snu-links.js's openDeleteCategoryModal) —
   move-then-delete vs delete-everything option cards. */
.admin-modal--delcat { width: min(560px, 100%); }
.delcat-sub { font-size: 13px; color: var(--muted); margin: 0 0 14px; }
.delcat-opt {
  border: 1px solid var(--line); border-radius: 12px; margin-bottom: 10px; background: var(--input-bg);
  transition: border-color .15s, box-shadow .15s, background .15s;
}
.delcat-opt.is-selected { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); background: var(--card); }
.delcat-opt--danger.is-selected { border-color: #DC2626; box-shadow: 0 0 0 3px color-mix(in srgb, #DC2626 14%, transparent); }
.delcat-opt-row { display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px; cursor: pointer; }
.delcat-opt-row input { margin-top: 3px; width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; flex: 0 0 auto; }
.delcat-opt--danger .delcat-opt-row input { accent-color: #DC2626; }
.delcat-opt-title { font-size: 13.5px; font-weight: 600; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; color: var(--fg); }
.delcat-opt-sub { display: block; font-size: 12px; color: var(--muted); margin-top: 3px; line-height: 1.5; }
.delcat-opt-sub strong { color: #DC2626; font-weight: 600; }
.delcat-badge {
  font-size: 10.5px; font-weight: 700; letter-spacing: .02em; color: #0E7A5F;
  background: color-mix(in srgb, #0E7A5F 14%, transparent); padding: 2px 8px; border-radius: 999px;
}
[data-theme="dark"] .delcat-badge { color: #34D399; background: color-mix(in srgb, #34D399 16%, transparent); }
.delcat-zone { padding: 0 14px 14px 39px; }
.delcat-zone[hidden] { display: none; }
.delcat-zone label { display: block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); margin-bottom: 6px; }
.delcat-zone select, .delcat-zone input[type="text"] {
  width: 100%; height: 36px; padding: 0 10px; border-radius: 8px; border: 1px solid var(--line);
  background: var(--card); color: var(--fg); font-size: 13px; font-family: inherit;
}
/* The "Type demo to confirm" sentence reads naturally, unlike the uppercase
   field-label style above (it's not labeling an input the way "Move
   applications to" labels the <select> next to it). */
.delcat-zone[data-delcat-zone="all"] label {
  font-size: 13px; font-weight: 400; text-transform: none; letter-spacing: normal; color: var(--muted);
}
.delcat-zone code {
  font-family: ui-monospace, "SF Mono", monospace; font-size: 12.5px; font-weight: 600;
  color: var(--accent); background: var(--accent-soft); padding: 2px 7px; border-radius: 5px;
}
.delcat-apps { margin: 4px 0 0; }
.delcat-apps summary {
  list-style: none; cursor: pointer; user-select: none; font-size: 12.5px; font-weight: 600; color: var(--accent);
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 2px;
}
.delcat-apps summary::-webkit-details-marker { display: none; }
.delcat-chev { display: inline-block; transition: transform .15s; font-size: 9px; }
.delcat-apps[open] .delcat-chev { transform: rotate(90deg); }
.delcat-app-grid {
  margin-top: 8px; display: flex; flex-wrap: wrap; gap: 6px; border: 1px solid var(--line); border-radius: 10px;
  padding: 10px 12px; background: var(--input-bg); max-height: 150px; overflow-y: auto;
}
.delcat-app-grid span {
  font-size: 12px; color: var(--fg); background: var(--card); border: 1px solid var(--line);
  border-radius: 999px; padding: 3px 10px;
}

/* Icon/color combo dropdowns (category + application edit forms) — a
   native <select> can only ever show plain text, so these are custom
   listboxes: the trigger button doubles as the "preview" (renders the
   chosen icon/swatch inline), and every option in the panel renders its
   own icon glyph or color swatch next to its name. */
.admin-combo { position: relative; }
.admin-combo-trigger {
  width: 100%; height: 38px; padding: 0 12px; border-radius: 9px; border: 1px solid var(--line);
  background: var(--input-bg); color: var(--fg); font-size: 13px; font-family: inherit; cursor: pointer;
  display: flex; align-items: center; gap: 9px; text-align: left;
}
.admin-combo-trigger:hover { border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); }
.admin-combo[data-open] .admin-combo-trigger { border-color: var(--accent); }
.admin-combo-trigger-label { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-combo-trigger-icon { flex: 0 0 auto; display: grid; place-items: center; width: 20px; height: 20px; }
.admin-combo-trigger-swatch { flex: 0 0 auto; width: 16px; height: 16px; border-radius: 5px; border: 1px solid var(--line); }
.admin-combo-caret { flex: 0 0 auto; color: var(--muted); display: grid; place-items: center; transition: transform .12s; }
.admin-combo[data-open] .admin-combo-caret { transform: rotate(180deg); }

/* A wrapped grid of chips (not a one-per-row list) — same panel, same
   scrollbar treatment, for both the icon and color combos, so scrolling
   through 50+ icons or a dozen colors feels and looks identical. */
.admin-combo-panel {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 30;
  background: var(--card); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 14px 34px rgba(0,0,0,.2); max-height: 240px; overflow-y: auto; padding: 8px;
  display: flex; flex-wrap: wrap; align-content: flex-start; gap: 6px;
  scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--muted) 55%, transparent) transparent;
}
.admin-combo-panel[hidden] { display: none; }
.admin-combo-panel::-webkit-scrollbar { width: 8px; }
.admin-combo-panel::-webkit-scrollbar-track { background: transparent; margin: 4px; }
.admin-combo-panel::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--muted) 55%, transparent); border-radius: 4px; }
.admin-combo-panel::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--muted) 80%, transparent); }

.admin-combo-option {
  flex: 0 0 auto; width: auto; display: flex; align-items: center; gap: 8px; padding: 7px 12px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--input-bg); color: var(--fg); font-size: 12.5px; font-family: inherit;
  cursor: pointer; text-align: left; transition: background .12s, border-color .12s, color .12s;
}
.admin-combo-option:hover { background: var(--row-hover); border-color: color-mix(in srgb, var(--accent) 35%, var(--line)); }
.admin-combo-option.is-selected { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); font-weight: 600; }
.admin-combo-option-icon { flex: 0 0 auto; display: grid; place-items: center; width: 18px; height: 18px; }
/* The swatch is the whole point of a color chip (no hex code shown next to
   it), so it's bigger here than the small preview in the closed trigger. */
.admin-combo-option-swatch { flex: 0 0 auto; width: 20px; height: 20px; border-radius: 6px; border: 1px solid var(--line); }
/* flex-basis:100% forces this row to break onto its own line at the end of
   the wrapped grid, same trick used for .lp-footer-link-name wrapping. */
.admin-combo-option-custom {
  flex: 1 0 100%; border-top: 1px solid var(--line); border-radius: 0; margin-top: 4px; padding-top: 12px;
}
.admin-combo-option-custom input[type="color"] {
  flex: 0 0 auto; width: 26px; height: 26px; padding: 0; border: 1px solid var(--line); border-radius: 6px; background: none; cursor: pointer;
}

.admin-tree { list-style: none; margin: 0; padding: 0; }
.admin-tree ul { list-style: none; margin: 2px 0 4px 22px; padding: 0; border-left: 1px dashed var(--line); }
.admin-tree-row { display: flex; align-items: center; gap: 8px; padding: 7px 8px; border-radius: 8px; }
.admin-tree-row:hover { background: var(--row-hover); }
/* Direct child only — the row's own leading type icon (folder/doc) and the
   SSO badge, not the action buttons' icons nested two levels down inside
   them, which should keep each button's own color (e.g. .admin-btn--danger's
   red) instead of being forced muted. */
.admin-tree-row > span[data-icon] { color: var(--muted); flex-shrink: 0; }
.admin-tree-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; flex-shrink: 0; border: none; background: transparent;
  color: var(--muted); cursor: pointer; padding: 0; border-radius: 5px;
}
.admin-tree-toggle:hover { background: var(--row-hover); }
.admin-tree-toggle span[data-icon] { transition: transform .12s; }
.admin-tree-toggle--spacer { cursor: default; }
.admin-tree-name { flex: 1; min-width: 0; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-tree-sso {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 24px; height: 24px; border-radius: 7px; border: 1px solid var(--line);
  background: var(--card); color: var(--fg); cursor: pointer; padding: 0;
  font: inherit; transition: background .12s, border-color .12s;
}
.admin-tree-sso:hover { background: var(--row-hover); }
.admin-tree-row .admin-tree-sso.is-on {
  color: #059669; background: color-mix(in srgb, #059669 12%, transparent);
  border-color: color-mix(in srgb, #059669 40%, var(--line));
}
.admin-tree-row .admin-tree-sso.is-on:hover {
  background: color-mix(in srgb, #059669 20%, transparent);
}
.admin-tree-actions { display: flex; gap: 4px; flex-shrink: 0; }
.admin-tree-actions .admin-btn { padding: 0 8px; }
