/* Nabati SSO — shared visual language, taken from the Care Docs portal
   (caredocs.staging.nabatisnack.co.id/login): light zinc surfaces, Nabati red
   as the only accent, Plus Jakarta Sans for headings, Inter for text and Sora
   for the one display headline on the sign-in page.

   No inline styles anywhere: the Content-Security-Policy is style-src 'self'.
   The fonts are self-hosted for the same reason — font-src is 'self', so the
   Google Fonts stylesheet the portal links would be blocked here. */

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/inter.woff2") format("woff2");
}

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

@font-face {
  font-family: "Sora";
  font-style: normal;
  font-weight: 600 800;
  font-display: swap;
  src: url("../fonts/sora.woff2") format("woff2");
}

:root {
  color-scheme: light;

  /* Nabati red: the portal's --primary, oklch(58% .21 25.5). */
  --primary: #db2b31;
  --primary-hover: #c4252b;
  --primary-soft: rgba(219, 43, 49, .08);
  --primary-ring: rgba(219, 43, 49, .18);
  --on-primary: #ffffff;

  /* Zinc neutrals, the same scale the portal uses. */
  --bg: #faf8f9;
  --bg-2: #f5f2f3;
  --bg-3: #e8e6e7;
  --surface: #ffffff;
  --surface-2: #fafafa;
  --line: #e4e4e7;
  --line-strong: #d4d4d8;
  --text: #18181b;
  --text-2: #52525b;
  --muted: #71717a;
  --faint: #a1a1aa;

  --ok: #16a34a;
  --ok-bg: #f0fdf4;
  --ok-border: #bbf7d0;
  --ok-text: #15803d;
  --warn: #d97706;
  --danger: #dc2626;
  --danger-bg: #fef2f2;
  --danger-border: #fecaca;
  --danger-border-strong: #fca5a5;
  --danger-text: #b91c1c;

  /* Translucent layers: the sign-in card, the sticky topbar, launcher tiles. */
  --glass: rgba(255, 255, 255, .72);
  --glass-border: rgba(255, 255, 255, .6);
  --topbar-bg: rgba(255, 255, 255, .85);
  --tile-bg: rgba(255, 255, 255, .96);

  /* An application's own colour, as used on its icon: full strength on a
     light page, lifted toward white on a dark one so dim brand colours stay
     readable. */
  --icon-ink: 100%;
  --icon-tint: 12%;

  --shadow: 0 20px 40px -24px rgba(24, 24, 27, .18);
  --tile-shadow: 0 8px 20px -14px rgba(24, 24, 27, .35);
  --overlay-shadow: 0 24px 64px -16px rgba(24, 24, 27, .35);
  --input-shadow: 0 1px 2px rgba(24, 24, 27, .04);
  --scrim: rgba(24, 24, 27, .4);

  --blob-1: rgba(254, 205, 211, .35);
  --blob-2: rgba(212, 212, 216, .4);

  /* The launcher backdrop takes its colours from the Care Docs sign-in page
     (caredocs.staging.nabatisnack.co.id/login): a light diagonal gradient
     (#faf8f9 to #e8e6e7) with a soft rose-200 wash at the top left and a
     zinc-300 wash at the bottom right. Care Docs draws those washes as
     blurred circles; radial gradients give the same falloff without a blur
     filter. Its pink and lilac waves, multiplied over the base, tint the lower
     half mauve; the rose, mauve-corner and bottom-tint layers reproduce that
     colour (matched against pixels sampled from the live page) without the
     wave shapes. The large faint diagonal facets of the SAP Fiori launchpad,
     the first three layers, take the waves' place. */
  --launcher-bg:
    linear-gradient(115deg, transparent 54%, rgba(255, 255, 255, .38) 54%, rgba(255, 255, 255, .38) 72%, transparent 72%),
    linear-gradient(245deg, transparent 62%, rgba(255, 255, 255, .26) 62%, rgba(255, 255, 255, .26) 84%, transparent 84%),
    linear-gradient(160deg, transparent 38%, rgba(90, 70, 75, .025) 38%, rgba(90, 70, 75, .025) 58%, transparent 58%),
    radial-gradient(900px 900px at 12% 6%, rgba(254, 205, 211, .4), transparent 62%),
    radial-gradient(900px 700px at 0% 48%, rgba(242, 196, 204, .5), transparent 65%),
    radial-gradient(1100px 800px at 100% 100%, rgba(186, 164, 180, .55), transparent 66%),
    linear-gradient(180deg, transparent 24%, rgba(212, 172, 194, .58) 100%),
    linear-gradient(135deg, #faf8f9 0%, #f5f2f3 50%, #e8e6e7 100%);

  /* The sign-in page: the launcher's family of facets, told apart from it.
     The facets run the other diagonal (65 and 295 degrees against the
     launcher's 115 and 245), one faint band is Nabati red instead of shade,
     and the mauve rises more gently, under the page's own rose and grey
     washes (.auth::before / ::after). */
  --auth-bg:
    linear-gradient(65deg, transparent 46%, rgba(255, 255, 255, .4) 46%, rgba(255, 255, 255, .4) 64%, transparent 64%),
    linear-gradient(295deg, transparent 58%, rgba(255, 255, 255, .28) 58%, rgba(255, 255, 255, .28) 80%, transparent 80%),
    linear-gradient(20deg, transparent 30%, rgba(219, 43, 49, .035) 30%, rgba(219, 43, 49, .035) 44%, transparent 44%),
    linear-gradient(180deg, transparent 34%, rgba(212, 172, 194, .38) 100%),
    linear-gradient(135deg, #faf8f9 0%, #f5f2f3 50%, #e8e6e7 100%);

  --radius: 16px;
  --radius-sm: 8px;

  --font: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-heading: "Plus Jakarta Sans", var(--font);
  --font-display: "Sora", var(--font);
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

/* Dark theme. It applies when the user picked it with the topbar toggle
   (data-theme="dark", set by theme.js), or when they picked nothing and the
   system is dark. The token list is written out twice because CSS cannot
   share one block between a media query and an attribute selector; keep the
   two identical. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --primary: #e5383e;
    --primary-hover: #ef4b51;
    --primary-soft: rgba(239, 68, 68, .14);
    --primary-ring: rgba(239, 68, 68, .32);
    --on-primary: #ffffff;

    --bg: #0f0f11;
    --bg-2: #131316;
    --bg-3: #17171a;
    --surface: #18181b;
    --surface-2: #1f1f23;
    --line: #2c2c32;
    --line-strong: #3f3f46;
    --text: #f4f4f5;
    --text-2: #d4d4d8;
    --muted: #a1a1aa;
    --faint: #71717a;

    --ok: #22c55e;
    --ok-bg: rgba(34, 197, 94, .12);
    --ok-border: rgba(34, 197, 94, .35);
    --ok-text: #86efac;
    --warn: #f59e0b;
    --danger: #f87171;
    --danger-bg: rgba(239, 68, 68, .12);
    --danger-border: rgba(239, 68, 68, .35);
    --danger-border-strong: rgba(239, 68, 68, .55);
    --danger-text: #fca5a5;

    --glass: rgba(24, 24, 27, .78);
    --glass-border: rgba(255, 255, 255, .08);
    --topbar-bg: rgba(15, 15, 17, .82);
    --tile-bg: rgba(24, 24, 27, .92);

    --icon-ink: 62%;
    --icon-tint: 20%;

    --shadow: 0 20px 40px -24px rgba(0, 0, 0, .6);
    --tile-shadow: 0 8px 20px -14px rgba(0, 0, 0, .7);
    --overlay-shadow: 0 24px 64px -16px rgba(0, 0, 0, .7);
    --input-shadow: none;
    --scrim: rgba(0, 0, 0, .6);

    --blob-1: rgba(219, 43, 49, .18);
    --blob-2: rgba(63, 63, 70, .35);

    --launcher-bg:
      linear-gradient(115deg, transparent 54%, rgba(255, 255, 255, .03) 54%, rgba(255, 255, 255, .03) 72%, transparent 72%),
      linear-gradient(245deg, transparent 62%, rgba(255, 255, 255, .02) 62%, rgba(255, 255, 255, .02) 84%, transparent 84%),
      linear-gradient(160deg, transparent 38%, rgba(0, 0, 0, .18) 38%, rgba(0, 0, 0, .18) 58%, transparent 58%),
      radial-gradient(1200px 640px at 0% 0%, rgba(219, 43, 49, .16), transparent 62%),
      radial-gradient(1100px 620px at 100% 0%, rgba(234, 120, 60, .1), transparent 60%),
      radial-gradient(1000px 720px at 50% 110%, rgba(219, 43, 49, .08), transparent 65%),
      linear-gradient(180deg, #131113 0%, #111113 55%, #0f0f11 100%);

    --auth-bg:
      linear-gradient(65deg, transparent 46%, rgba(255, 255, 255, .03) 46%, rgba(255, 255, 255, .03) 64%, transparent 64%),
      linear-gradient(295deg, transparent 58%, rgba(255, 255, 255, .02) 58%, rgba(255, 255, 255, .02) 80%, transparent 80%),
      linear-gradient(20deg, transparent 30%, rgba(219, 43, 49, .07) 30%, rgba(219, 43, 49, .07) 44%, transparent 44%),
      linear-gradient(135deg, #131113 0%, #111113 55%, #0f0f11 100%);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --primary: #e5383e;
  --primary-hover: #ef4b51;
  --primary-soft: rgba(239, 68, 68, .14);
  --primary-ring: rgba(239, 68, 68, .32);
  --on-primary: #ffffff;

  --bg: #0f0f11;
  --bg-2: #131316;
  --bg-3: #17171a;
  --surface: #18181b;
  --surface-2: #1f1f23;
  --line: #2c2c32;
  --line-strong: #3f3f46;
  --text: #f4f4f5;
  --text-2: #d4d4d8;
  --muted: #a1a1aa;
  --faint: #71717a;

  --ok: #22c55e;
  --ok-bg: rgba(34, 197, 94, .12);
  --ok-border: rgba(34, 197, 94, .35);
  --ok-text: #86efac;
  --warn: #f59e0b;
  --danger: #f87171;
  --danger-bg: rgba(239, 68, 68, .12);
  --danger-border: rgba(239, 68, 68, .35);
  --danger-border-strong: rgba(239, 68, 68, .55);
  --danger-text: #fca5a5;

  --glass: rgba(24, 24, 27, .78);
  --glass-border: rgba(255, 255, 255, .08);
  --topbar-bg: rgba(15, 15, 17, .82);
  --tile-bg: rgba(24, 24, 27, .92);

  --icon-ink: 62%;
  --icon-tint: 20%;

  --shadow: 0 20px 40px -24px rgba(0, 0, 0, .6);
  --tile-shadow: 0 8px 20px -14px rgba(0, 0, 0, .7);
  --overlay-shadow: 0 24px 64px -16px rgba(0, 0, 0, .7);
  --input-shadow: none;
  --scrim: rgba(0, 0, 0, .6);

  --blob-1: rgba(219, 43, 49, .18);
  --blob-2: rgba(63, 63, 70, .35);

  --launcher-bg:
    linear-gradient(115deg, transparent 54%, rgba(255, 255, 255, .03) 54%, rgba(255, 255, 255, .03) 72%, transparent 72%),
    linear-gradient(245deg, transparent 62%, rgba(255, 255, 255, .02) 62%, rgba(255, 255, 255, .02) 84%, transparent 84%),
    linear-gradient(160deg, transparent 38%, rgba(0, 0, 0, .18) 38%, rgba(0, 0, 0, .18) 58%, transparent 58%),
    radial-gradient(1200px 640px at 0% 0%, rgba(219, 43, 49, .16), transparent 62%),
    radial-gradient(1100px 620px at 100% 0%, rgba(234, 120, 60, .1), transparent 60%),
    radial-gradient(1000px 720px at 50% 110%, rgba(219, 43, 49, .08), transparent 65%),
    linear-gradient(180deg, #131113 0%, #111113 55%, #0f0f11 100%);

  --auth-bg:
    linear-gradient(65deg, transparent 46%, rgba(255, 255, 255, .03) 46%, rgba(255, 255, 255, .03) 64%, transparent 64%),
    linear-gradient(295deg, transparent 58%, rgba(255, 255, 255, .02) 58%, rgba(255, 255, 255, .02) 80%, transparent 80%),
    linear-gradient(20deg, transparent 30%, rgba(219, 43, 49, .07) 30%, rgba(219, 43, 49, .07) 44%, transparent 44%),
    linear-gradient(135deg, #131113 0%, #111113 55%, #0f0f11 100%);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
}

body {
  font-family: var(--font);
  background: linear-gradient(135deg, var(--bg), var(--bg-2) 55%, var(--bg-3));
  background-attachment: fixed;
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  line-height: 1.55;
}

::selection { background: var(--primary-soft); color: var(--primary); }

a { color: var(--primary); text-decoration: none; }
a:hover { text-decoration: underline; }

.hidden { display: none !important; }

h1, h2, h3 { font-family: var(--font-heading); color: var(--text); }
h1 { font-size: 24px; font-weight: 800; margin: 0 0 6px; letter-spacing: -.5px; line-height: 1.2; }
h2 { font-size: 16px; font-weight: 700; margin: 0 0 14px; letter-spacing: -.2px; }
.sub { color: var(--muted); font-size: 14px; font-weight: 500; margin: 0 0 24px; }

/* ---------- brand ---------- */

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 28px;
}

/* The Nabati mark is a wide wordmark (about 1.6:1), so it is sized by height. */
.brand-logo { display: block; height: 36px; width: auto; }

/* Kept for the consent page, where the mark is the requesting application's. */
.brand-mark {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: var(--primary-soft);
  color: var(--primary);
  display: grid;
  place-items: center;
  font-weight: 800;
  font-size: 18px;
  font-family: var(--font-heading);
}

.brand-name {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 16px;
  letter-spacing: -.3px;
  color: var(--text);
}

.brand-sub { font-size: 12px; color: var(--muted); font-weight: 500; }

/* ---------- sign-in page ---------- */

.auth {
  position: relative;
  min-height: 100vh;
  overflow-x: hidden;
  background: var(--auth-bg);
  background-attachment: fixed;
}

/* Two soft colour washes behind the page, as on the portal. Decorative only. */
.auth::before,
.auth::after {
  content: "";
  position: fixed;
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
}

.auth::before {
  top: -15%;
  left: -10%;
  width: 60vw;
  height: 60vw;
  background: var(--blob-1);
  filter: blur(120px);
}

.auth::after {
  bottom: -15%;
  right: -10%;
  width: 50vw;
  height: 50vw;
  background: var(--blob-2);
  filter: blur(100px);
}

.auth-shell {
  position: relative;
  z-index: 1;
  max-width: 1280px;
  min-height: 100vh;
  margin: 0 auto;
  padding: 40px 32px;
  display: flex;
  flex-direction: column;
}

.auth-top { display: flex; align-items: center; gap: 16px; }
.auth-top .brand-logo { height: 48px; }

.auth-top .brand-name { font-size: 28px; letter-spacing: -.8px; }

.auth-main {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 48px;
  padding: 48px 0;
}

.auth-hero { max-width: 560px; }

.auth-hero h2 {
  font-family: var(--font-display);
  font-size: 48px;
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -1.2px;
  margin: 0 0 24px;
}

.auth-hero h2 span { color: var(--primary); }

.auth-hero p {
  color: var(--text-2);
  font-size: 18px;
  font-weight: 600;
  line-height: 1.6;
  margin: 0;
}

.auth-card {
  width: 100%;
  max-width: 440px;
  flex-shrink: 0;
  background: var(--glass);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 40px;
}

.auth-card h1 {
  font-size: 44px;
  letter-spacing: -1.4px;
  margin-bottom: 12px;
}

.auth-card .sub { font-size: 16px; font-weight: 600; margin-bottom: 36px; }

.auth-card label {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .2em;
  color: var(--faint);
  margin: 0 0 8px 4px;
}

.auth-card input[type="email"],
.auth-card input[type="password"] {
  height: 56px;
  padding: 0 16px;
  font-size: 16px;
  font-weight: 600;
}

.auth-card .field { margin-bottom: 24px; }

.auth-card .btn {
  height: 56px;
  margin-top: 8px;
  font-family: var(--font-heading);
  font-size: 15px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
}

/* The arrow is drawn in CSS so login.js can keep setting the label with
   textContent without wiping it out. */
.auth-card .btn::after {
  content: "→";
  font-family: var(--font);
  transition: transform .15s ease-out;
}

.auth-card .btn:hover::after { transform: translateX(4px); }
.auth-card .btn:disabled::after { content: none; }

.auth-foot {
  text-align: center;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--faint);
}

/* ---------- centered card layout (consent, errors, sign-out) ---------- */

.center-wrap {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 32px 20px;
}

.card {
  width: 100%;
  max-width: 440px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 36px 32px;
}

.card.wide { max-width: 520px; }

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

label {
  display: block;
  font-size: 12px;
  color: var(--text-2);
  margin: 0 0 6px;
  font-weight: 600;
}

input[type="text"], input[type="email"], input[type="password"], input[type="url"], input[type="search"], select, textarea {
  width: 100%;
  padding: 10px 12px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-size: 14px;
  font-family: inherit;
  box-shadow: var(--input-shadow);
  transition: border-color .15s, background-color .15s, box-shadow .15s;
}

input::placeholder, textarea::placeholder { color: var(--faint); }

input:focus, select:focus, textarea:focus {
  outline: none;
  background: var(--surface);
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-ring);
}

.field { margin-bottom: 16px; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: 100%;
  padding: 10px 16px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--primary);
  color: var(--on-primary);
  font-size: 14px;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  transition: background-color .15s, border-color .15s, color .15s, transform .1s;
}

.btn:hover { background: var(--primary-hover); text-decoration: none; }
.btn:active { transform: scale(.98); }
.btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--primary-ring); }
.btn:disabled { background: var(--line-strong); color: var(--muted); cursor: not-allowed; transform: none; }

.btn.secondary {
  background: var(--surface);
  border-color: var(--line);
  color: var(--text);
}

.btn.secondary:hover { background: var(--surface-2); border-color: var(--line-strong); }

.btn.danger { background: var(--surface); border-color: var(--danger-border); color: var(--danger); }
.btn.danger:hover { background: var(--danger-bg); border-color: var(--danger-border-strong); }

.btn.small { width: auto; padding: 6px 12px; font-size: 12px; white-space: nowrap; }
.btn svg { width: 16px; height: 16px; flex-shrink: 0; }
.btn.small svg { width: 14px; height: 14px; }
.btn-row { display: flex; gap: 12px; }

.alert {
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 500;
  margin-bottom: 16px;
  border: 1px solid transparent;
}

.alert.error { background: var(--danger-bg); border-color: var(--danger-border); color: var(--danger-text); }
.alert.ok { background: var(--ok-bg); border-color: var(--ok-border); color: var(--ok-text); }
.alert.info { background: var(--surface-2); border-color: var(--line); color: var(--text-2); }
/* The "signed out" notice on the login page: green text, neutral box. */
.alert.signed-out { color: var(--ok-text); }

.hint { font-size: 12px; color: var(--muted); margin-top: 16px; text-align: center; }

/* ---------- app shell (launcher, admin, account) ---------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 24px;
  background: var(--topbar-bg);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}

.topbar .brand { margin-bottom: 0; }
.topbar .brand-name, .topbar .btn { white-space: nowrap; }
.topbar .brand-logo { height: 32px; }

.topnav { display: flex; gap: 4px; align-items: center; }

.topnav a {
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
}

.topnav a:hover { background: var(--bg-2); color: var(--text); text-decoration: none; }
.topnav a.active { background: var(--primary-soft); color: var(--primary); }

.who { display: flex; align-items: center; gap: 12px; font-size: 13px; }

.avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--primary);
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--on-primary);
}

.page { max-width: 1120px; margin: 0 auto; padding: 36px 24px 72px; }

.page-head { margin-bottom: 28px; }
.page-head h1 { font-size: 28px; }

/* ---------- launcher ---------- */

/* A smooth pastel wash in the manner of SAP Fiori's Horizon theme: three soft
   warm colour fields that fade into the page colour, fixed to the viewport so
   the tiles scroll over it. No blue, no shapes, no hard edges. The colours are
   theme tokens (--launcher-bg). */
body.launcher {
  background: var(--launcher-bg);
  background-attachment: fixed;
}

/* Group tabs, below Favorites: an underline tab strip with the grid/list
   switch at its right end. */
.launcher-tabs {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 0 0 16px;
  border-bottom: 1px solid var(--line);
}

.group-tabs {
  flex: 1;
  min-width: 0;
  display: flex;
  gap: 4px;
  overflow-x: auto;
  scrollbar-width: none;
}

.group-tabs::-webkit-scrollbar { display: none; }

.group-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  margin-bottom: -1px;
  padding: 10px 14px;
  border: none;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--muted);
  font: 600 14px var(--font);
  white-space: nowrap;
  cursor: pointer;
  transition: color .15s, border-color .15s;
}

.group-tab:hover { color: var(--text); }
.group-tab:focus-visible { outline: 2px solid var(--primary); outline-offset: -4px; border-radius: 6px; }
.group-tab[aria-selected="true"] { color: var(--primary); border-bottom-color: var(--primary); }

.tab-count {
  min-width: 20px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--bg-2);
  font-size: 11px;
  line-height: 18px;
  text-align: center;
}

.view-toggle {
  display: flex;
  flex-shrink: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  overflow: hidden;
}

.view-toggle button {
  width: 34px;
  height: 30px;
  display: grid;
  place-items: center;
  border: none;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}

.view-toggle button + button { border-left: 1px solid var(--line); }
.view-toggle button:hover { color: var(--text); }
.view-toggle button[aria-pressed="true"] { background: var(--bg-2); color: var(--text); }
.view-toggle button:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.view-toggle svg { width: 16px; height: 16px; }

body.launcher .empty { background: var(--tile-bg); }

/* The backdrop is deepest behind the page heading and Favorites, where the
   muted grey falls short of a readable contrast; the secondary text colour
   holds it in both themes. */
body.launcher .page-head .sub,
body.launcher .section-title { color: var(--text-2); }

.launcher-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.section-title {
  font-family: var(--font);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 12px;
}

.launcher-section { margin-bottom: 32px; }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
  gap: 12px;
}

/* Compact tile: icon, name and a one-line description in a row, with the
   favourite star on the right. The link and the star are siblings, not
   nested, because a button inside a link is invalid and unreliable. */
.tile {
  position: relative;
  background: var(--tile-bg);
  border: 1px solid var(--line);
  border-radius: 12px;
  /* Clips the accent bar to the rounded corners. It would clip an outer focus
     ring too, which is why the link draws its ring inside. */
  overflow: hidden;
  transition: transform .15s ease-out, border-color .15s, box-shadow .15s;
}

/* The application's colour as a thin bar along the top edge. */
.tile::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: var(--tile-color, var(--primary));
  pointer-events: none;
}

.tile:hover {
  transform: translateY(-1px);
  border-color: var(--tile-color, var(--primary));
  box-shadow: var(--tile-shadow);
}

.tile-link {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  min-height: 92px;
  padding: 19px 44px 16px 16px;
  color: inherit;
  border-radius: 12px;
}

.tile-link:hover { text-decoration: none; }
.tile-link:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

.tile-icon,
.app-icon {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  font-size: 13px;
  font-weight: 700;
  font-family: var(--font-heading);
  background: color-mix(in srgb, var(--tile-color, var(--primary)) var(--icon-tint), transparent);
  color: color-mix(in srgb, var(--tile-color, var(--primary)) var(--icon-ink), #ffffff);
}

.tile-icon svg,
.app-icon svg { width: 20px; height: 20px; }

.app-icon.small { width: 28px; height: 28px; border-radius: 8px; font-size: 11px; }
.app-icon.small svg { width: 15px; height: 15px; }
.app-icon.large { width: 48px; height: 48px; border-radius: 12px; font-size: 16px; }
.app-icon.large svg { width: 24px; height: 24px; }

.tile-text { min-width: 0; }
.tile-name { font-family: var(--font-heading); font-weight: 700; font-size: 14px; line-height: 1.3; margin-bottom: 2px; }

/* Two lines of description, always reserved, so every tile in a row is the
   same height whether its text is short or long. */
.tile-desc {
  font-size: 12px;
  line-height: 1.45;
  min-height: calc(2 * 1.45em);
  color: var(--muted);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

/* Group and t-codes, shown only in the list view where a row has room. */
.tile-meta { display: none; }
.tile-group { font-size: 12px; color: var(--muted); white-space: nowrap; }

/* List view: one row per application inside a single panel, the accent moved
   from the top edge to the left. */
.grid.list {
  grid-template-columns: 1fr;
  gap: 0;
  background: var(--tile-bg);
  border: 1px solid var(--line);
  border-radius: 12px;
  overflow: hidden;
}

.grid.list .tile {
  border: none;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  background: transparent;
}

.grid.list .tile:last-child { border-bottom: none; }
.grid.list .tile:hover { transform: none; box-shadow: none; background: var(--surface-2); }
.grid.list .tile::before { inset: 0 auto 0 0; width: 3px; height: auto; }

.grid.list .tile-link {
  align-items: center;
  min-height: 0;
  padding: 10px 48px 10px 18px;
  border-radius: 0;
}

.grid.list .tile-icon { width: 32px; height: 32px; border-radius: 8px; }
.grid.list .tile-icon svg { width: 17px; height: 17px; }
.grid.list .tile-text { flex: 1; }
.grid.list .tile-name { margin-bottom: 0; }
.grid.list .tile-desc { min-height: 0; -webkit-line-clamp: 1; line-clamp: 1; }

.grid.list .tile-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

.grid.list .tile-meta .chip { margin: 0; }
.grid.list .fav-btn { top: 50%; transform: translateY(-50%); }

.fav-btn {
  position: absolute;
  top: 14px;
  right: 8px;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--line-strong);
  cursor: pointer;
  transition: color .15s, background-color .15s;
}

.fav-btn svg { width: 16px; height: 16px; }
.fav-btn:hover { background: var(--bg-2); color: var(--warn); }
.fav-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--primary-ring); }
.fav-btn.on { color: var(--warn); }
.fav-btn.on svg { fill: currentColor; }

/* Unstarred stars stay out of the way until the tile is pointed at. */
@media (hover: hover) {
  .fav-btn:not(.on) { opacity: 0; }
  .tile:hover .fav-btn,
  .fav-btn:focus-visible { opacity: 1; }
}

.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }

.chip {
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--text-2);
  font-family: var(--mono);
}

.chip.on { background: var(--ok-bg); border-color: var(--ok-border); color: var(--ok-text); }
.chip.off { background: var(--bg-2); color: var(--faint); }

.empty {
  padding: 48px 24px;
  text-align: center;
  color: var(--muted);
  background: var(--surface);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
}

/* ---------- panels and tables ---------- */

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
  margin-bottom: 20px;
}

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 16px;
}

.panel-head h2 { margin: 0; }

.panel-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

input[type="search"].table-search {
  width: 260px;
  padding: 6px 10px;
  font-size: 13px;
}

td.table-empty { padding: 24px 12px; text-align: center; }

/* A text button, for "+N more" / "Show less" inside a list of chips. */
.link-btn {
  padding: 2px 6px;
  border: none;
  border-radius: 6px;
  background: none;
  color: var(--primary);
  font: 600 12px var(--font);
  cursor: pointer;
}

.link-btn:hover { background: var(--primary-soft); }
.link-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }

table { width: 100%; border-collapse: collapse; font-size: 13px; }
th { text-align: left; font-size: 10px; text-transform: uppercase; letter-spacing: .12em; color: var(--faint); padding: 0 12px 10px; font-weight: 700; }
td { padding: 12px; border-top: 1px solid var(--line); vertical-align: top; }
tr:hover td { background: var(--surface-2); }

.mono { font-family: var(--mono); font-size: 12px; }
/* Long URLs and ids in table cells wrap instead of pushing the table past
   its panel. */
td.mono { overflow-wrap: anywhere; }
/* A table whose columns must not wrap scrolls sideways inside its panel when
   the viewport is too narrow, instead of spilling out of it. */
.table-scroll { overflow-x: auto; }
/* The free-text column: it takes the width the other columns leave and wraps
   inside it, but never below a readable minimum — below that the table
   scrolls. Without the width, automatic layout hands the spare width to the
   widest column; without the minimum, overflow-wrap lets it shrink to one
   character. */
td.grow { width: 100%; }
.cell-text { min-width: 12rem; overflow-wrap: anywhere; }
.muted { color: var(--muted); }
.right { text-align: right; }
.nowrap { white-space: nowrap; }

.tabs { display: flex; gap: 4px; margin-bottom: 20px; border-bottom: 1px solid var(--line); }

.tab {
  padding: 10px 16px;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  background: none;
  border-top: none;
  border-left: none;
  border-right: none;
  font-family: inherit;
}

.tab:hover { color: var(--text); }
.tab.active { color: var(--primary); border-bottom-color: var(--primary); }

/* ---------- theme toggle ---------- */

.theme-toggle {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text-2);
  cursor: pointer;
  transition: border-color .15s, background-color .15s, color .15s;
}

.theme-toggle:hover { border-color: var(--line-strong); color: var(--text); }
.theme-toggle:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--primary-ring); }
.theme-toggle svg { width: 16px; height: 16px; }
.auth-top .theme-toggle { margin-left: auto; }

/* ---------- command palette (Cmd+K) ---------- */

.topbar-search {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 220px;
  height: 34px;
  padding: 0 8px 0 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--muted);
  font: 500 13px var(--font);
  cursor: pointer;
  transition: border-color .15s, background-color .15s;
}

.topbar-search:hover { border-color: var(--line-strong); background: var(--surface); }
.topbar-search:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--primary-ring); }
.topbar-search svg { width: 15px; height: 15px; flex-shrink: 0; }
.topbar-search .label { flex: 1; text-align: left; }

kbd {
  display: inline-block;
  padding: 1px 6px;
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: 6px;
  background: var(--surface);
  color: var(--text-2);
  font: 600 11px var(--font);
  line-height: 1.5;
}

.palette-backdrop {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 12vh 16px 16px;
  background: var(--scrim);
}

.palette {
  width: 100%;
  max-width: 600px;
  max-height: 70vh;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--overlay-shadow);
  overflow: hidden;
}

.palette-input-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 16px;
  border-bottom: 1px solid var(--line);
  color: var(--muted);
}

.palette-input-row svg { width: 18px; height: 18px; flex-shrink: 0; }

.palette-input-row input[type="text"] {
  height: 56px;
  padding: 0;
  border: none;
  background: transparent;
  box-shadow: none;
  font-size: 16px;
  font-weight: 500;
}

.palette-input-row input[type="text"]:focus { box-shadow: none; background: transparent; }

.palette-list { list-style: none; margin: 0; padding: 8px; overflow-y: auto; }

.palette-group {
  padding: 8px 8px 4px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--faint);
}

.palette-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px;
  border-radius: 10px;
  cursor: pointer;
}

.palette-item.active { background: var(--primary-soft); }
.palette-item-text { flex: 1; min-width: 0; }
.palette-item-title { font-size: 14px; font-weight: 600; color: var(--text); }

.palette-item-sub {
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.palette-code {
  flex-shrink: 0;
  padding: 2px 8px;
  border-radius: 6px;
  background: var(--bg-2);
  color: var(--text-2);
  font: 600 12px var(--mono);
}

.palette-item.active .palette-code { background: var(--surface); color: var(--primary); }
.palette-codes { display: flex; gap: 4px; flex-shrink: 0; }
.palette-code.more { color: var(--muted); }
.palette-empty { padding: 24px 16px; text-align: center; color: var(--muted); font-size: 13px; }

.palette-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  padding: 10px 16px;
  border-top: 1px solid var(--line);
  background: var(--surface-2);
  font-size: 11px;
  color: var(--muted);
}

/* ---------- admin: icon picker and shortcuts ---------- */

.modal.wide { max-width: 680px; }

.app-cell { display: flex; align-items: flex-start; gap: 12px; min-width: 220px; }
.app-group { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); margin-top: 2px; }
.app-cell .chips { margin-top: 6px; }

.icon-picker { display: grid; gap: 12px; }

.icon-preview {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}

.icon-preview-name { font-weight: 600; font-size: 14px; }
.icon-preview-sub { font-size: 12px; color: var(--muted); }

.icon-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));
  gap: 6px;
  max-height: 188px;
  overflow-y: auto;
  padding: 2px;
}

.icon-option {
  height: 40px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
  transition: border-color .15s, background-color .15s, color .15s;
}

.icon-option svg { width: 18px; height: 18px; }
.icon-option:hover { border-color: var(--line-strong); color: var(--text); }
.icon-option:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--primary-ring); }

/* The ring is in the brand colour, not the application's: a dark grey
   application colour would otherwise make the selection invisible in the
   dark theme. */
.icon-option.selected {
  box-shadow: 0 0 0 2px var(--primary-ring);
  border-color: var(--tile-color, var(--primary));
  background: color-mix(in srgb, var(--tile-color, var(--primary)) var(--icon-tint), transparent);
  color: color-mix(in srgb, var(--tile-color, var(--primary)) var(--icon-ink), #ffffff);
}

.icon-option.text-label { font: 700 12px var(--font-heading); }

.shortcut-rows { display: grid; gap: 8px; margin-bottom: 8px; }

.shortcut-row {
  display: grid;
  grid-template-columns: 110px 1fr 1.4fr 32px;
  gap: 8px;
  align-items: center;
}

.shortcut-row input.code { font-family: var(--mono); text-transform: uppercase; }

.icon-btn {
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
}

.icon-btn:hover { color: var(--danger); border-color: var(--danger-border); }
.icon-btn svg { width: 15px; height: 15px; }

.field-hint { font-size: 12px; color: var(--muted); margin: -2px 0 8px; }

/* ---------- pager ---------- */

.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}

.pager-info { font-size: 12px; color: var(--muted); }
.pager-pages { display: flex; align-items: center; gap: 4px; }

.page-btn {
  min-width: 32px;
  height: 32px;
  padding: 0 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-2);
  font: 600 13px var(--font);
  cursor: pointer;
  transition: background-color .15s, border-color .15s, color .15s;
}

.page-btn:hover:not(:disabled) { background: var(--surface-2); border-color: var(--line-strong); color: var(--text); }
.page-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--primary-ring); }
.page-btn:disabled { cursor: default; color: var(--faint); background: var(--surface); }
.page-btn.active,
.page-btn.active:disabled { background: var(--primary); border-color: var(--primary); color: var(--on-primary); }

.page-gap { min-width: 20px; text-align: center; color: var(--faint); font-size: 13px; }

/* ---------- modal ---------- */

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  display: grid;
  place-items: center;
  padding: 20px;
  z-index: 60;
}

.modal {
  width: 100%;
  max-width: 520px;
  max-height: 86vh;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 24px;
  box-shadow: var(--overlay-shadow);
}

.modal h2 { margin-bottom: 20px; }

/* A dialog whose content changes size while it is open (a filtered list)
   keeps one height, and its buttons stay at the bottom instead of following
   the content up and down. Long content still scrolls inside it. */
.modal.fixed { height: min(86vh, 720px); display: flex; flex-direction: column; }
.modal.fixed > form { flex: 1 0 auto; display: flex; flex-direction: column; }
/* The negative margin and the bottom padding both equal the modal's padding:
   the bar reaches the dialog's bottom edge whether the list is short (resting
   at the end of the form) or long (stuck while it scrolls), so the buttons
   never move, and no scrolled content shows beneath them. */
.modal.fixed > form > .btn-row {
  position: sticky;
  bottom: -24px;
  margin: auto 0 -24px;
  padding: 12px 0 24px;
  background: var(--surface);
  border-top: 1px solid var(--line);
}

.role-list { display: grid; gap: 8px; margin-top: 8px; }

.role-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  font-size: 13px;
}

.role-item input { width: auto; accent-color: var(--primary); }

/* Search and bulk check above the access editor. Sticky, because the dialog
   scrolls as a whole and the list of applications can be long. */
.access-toolbar {
  position: sticky;
  top: -24px; /* the modal's padding: stick to the visible top edge */
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
  padding: 12px 0;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.access-toolbar input[type="search"].table-search { flex: 1; width: auto; min-width: 160px; }
.access-count { flex-basis: 100%; font-size: 12px; }
.access-count:empty { display: none; }

.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 16px; margin-bottom: 24px; }
.stat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 16px 20px; }
.stat-value { font-family: var(--font-heading); font-size: 26px; font-weight: 800; letter-spacing: -.5px; }
.stat-label { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .12em; color: var(--faint); }

.scope-list { list-style: none; padding: 0; margin: 0 0 24px; display: grid; gap: 8px; }

.scope-list li {
  padding: 10px 14px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: 13px;
}

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

@media (max-width: 1023px) {
  .auth-hero { display: none; }
  .auth-main { justify-content: center; }
}

@media (max-width: 860px) {
  .topbar-search { min-width: 0; }
  .topbar-search .label, .topbar-search kbd { display: none; }
}

@media (max-width: 640px) {
  /* The logo carries the brand on its own; the wordmark gives way so the
     search, avatar and sign-out button still fit beside the navigation. */
  .topbar .brand-name { display: none; }
  /* The avatar repeats who is signed in, which the account page shows; it
     gives way so search, theme and sign-out stay on screen. */
  .topbar .avatar { display: none; }
  .launcher-tabs { gap: 8px; }
  .group-tab { padding: 10px; }
  .grid.list .tile-meta { display: none; }
  /* One tile per row: nothing to line up, so no reserved second line. */
  .tile-link { min-height: 0; }
  .tile-desc { min-height: 0; }
  .shortcut-row { grid-template-columns: 1fr 32px; }
  .shortcut-row input { grid-column: 1; }
  .shortcut-row .icon-btn { grid-column: 2; grid-row: 1; }
  .topbar { padding: 12px 16px; }
  .topnav a { padding: 6px 8px; }
  .who .muted { display: none; }
  .page { padding: 24px 16px 60px; }
  .card { padding: 28px 20px; }
  .auth-shell { padding: 24px 16px; }
  .auth-top .brand-logo { height: 36px; }
  .auth-top .brand-name { font-size: 22px; }
  .auth-main { padding: 32px 0; }
  .auth-card { padding: 28px 20px; }
  .auth-card h1 { font-size: 36px; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}
