/* ============================================================================
   Sercom Oil CMS Portal — styles

   Appearance is two independent axes, both applied as classes on <html>:
     • THEME    — colour tokens (.theme-* ; default = dark, no class)
     • FINISH   — surface rendering (.finish-glass / .finish-ink ; default flat)
   The no-flash <script> in each page's <head> re-applies the saved classes
   before first paint; nav.js builds the picker. See appearance registry in
   nav.js. Everything below is token-based so any theme × any finish combine.
   ========================================================================== */

/* ── Default theme (dark) : design tokens ──────────────────────────────── */
:root {
  color-scheme: dark;

  --background: #0f1115;      --foreground: #e6e8eb;
  --card: #151922;           --card-foreground: #e6e8eb;
  --popover: #11151c;        --popover-foreground: #e6e8eb;
  --muted: #11151c;          --muted-foreground: #9aa0aa;
  --border: #2a2e37;         --border-subtle: #20242d;   --input: #2a2e37;
  --surface-inset: #0d1014;  /* inputs on focus */

  --primary: #1f6feb;        --primary-foreground: #ffffff;
  --accent: #1b2029;         --accent-foreground: #e6e8eb;
  --ring: #1f6feb;

  --sidebar: #151922;        --sidebar-foreground: #c4c8cf;
  --sidebar-border: #2a2e37;
  --sidebar-primary: #1f6feb; --sidebar-primary-foreground: #ffffff;
  --sidebar-accent: #1b2029;  --sidebar-accent-foreground: #e6e8eb;
  --sidebar-ring: #1f6feb;

  /* Semantic — chip backgrounds are colour-mixed from these at use sites,
     so a theme only has to set the text colour and both adapt together. */
  --success: #6fd08c;        --success-hard: #2ea043;
  --warning: #f0c674;
  --destructive: #ff8a8a;    --destructive-hard: #f85149;
  --info: #6db3f2;           /* stable "expat" blue, independent of --primary */

  /* Geometry. Colour was themeable and shape was not, so every theme could only
     ever be this same portal in another palette. The radii were nine different
     hardcoded values across thirty-four rules, which is not a scale, it is what
     happens when each rule is written on its own. Four steps, and the values
     chosen so the default theme keeps close to the shape it had: 4, 5, 6 and
     7px all round to sm, 8, 9 and 10 to md. Thirteen of the thirty-four rules
     move as a result, none by more than two pixels: three from 10px, five from
     7px, two from 5px, two from 4px and one from 9px. An earlier version of this
     comment said only the three 10px rules moved, which was simply wrong, and a
     comment that undercounts its own blast radius is worse than none.

     A theme can now change the shape of the thing as well as its colour, which
     is most of what makes one design system look unlike another. */
  --radius-sm: 6px;   /* chips, inputs, small controls */
  --radius-md: 8px;   /* buttons, cards, the common case */
  --radius-lg: 12px;  /* panels and dialogs */
  --radius-pill: 999px;

  /* Surface weight. A design that sits flat on the page and one that floats
     above it differ mostly here, so it is a token rather than a constant. */
  --shadow-card: inset 0 1px 0 color-mix(in srgb, var(--foreground) 5%, transparent), 0 10px 24px -20px rgba(0, 0, 0, .5);
}

/* ── Light neutral base — shared by every light theme ──────────────────── */
.theme-light, .theme-ion, .theme-facet, .theme-badge,
.theme-berlin, .theme-amethyst, .theme-marigold {
  color-scheme: light;

  --background: #fafafa;     --foreground: #1a1a1a;
  --card: #ffffff;           --card-foreground: #1a1a1a;
  --popover: #ffffff;        --popover-foreground: #1a1a1a;
  --muted: #f1f1f2;          --muted-foreground: #6b7280;
  --border: #e4e4e7;         --border-subtle: #ececef;   --input: #e4e4e7;
  --surface-inset: #f4f4f5;

  --accent: #f1f1f2;         --accent-foreground: #1a1a1a;

  --sidebar: #ffffff;        --sidebar-foreground: #1a1a1a;
  --sidebar-border: #e4e4e7;
  --sidebar-accent: #f1f1f2; --sidebar-accent-foreground: #1a1a1a;

  /* Darkened semantics so status colours stay legible on white. */
  --success: #15803d;        --success-hard: #16a34a;
  --warning: #a16207;
  --destructive: #b91c1c;    --destructive-hard: #dc2626;
  --info: #1d4ed8;
}

/* Light themes: the sidebar mirrors the primary accent. */
.theme-light   { --primary:#2563eb; --primary-foreground:#ffffff; --ring:#2563eb;
                 --sidebar-primary:#2563eb; --sidebar-primary-foreground:#ffffff; --sidebar-ring:#2563eb; }
.theme-ion     { --primary:#c1121f; --primary-foreground:#ffffff; --ring:#c1121f; --accent:#fdeaea; --accent-foreground:#8a0d16;
                 --sidebar-primary:#c1121f; --sidebar-primary-foreground:#ffffff; --sidebar-ring:#c1121f; --sidebar-accent:#fdeaea; --sidebar-accent-foreground:#8a0d16; }
.theme-facet   { --primary:#2e7d32; --primary-foreground:#ffffff; --ring:#2e7d32; --accent:#e7f5e8; --accent-foreground:#1b5e20;
                 --sidebar-primary:#2e7d32; --sidebar-primary-foreground:#ffffff; --sidebar-ring:#2e7d32; --sidebar-accent:#e7f5e8; --sidebar-accent-foreground:#1b5e20; }
.theme-badge   { --primary:#0e7490; --primary-foreground:#ffffff; --ring:#0e7490; --accent:#e0f5f9; --accent-foreground:#075063;
                 --sidebar-primary:#0e7490; --sidebar-primary-foreground:#ffffff; --sidebar-ring:#0e7490; --sidebar-accent:#e0f5f9; --sidebar-accent-foreground:#075063; }
.theme-berlin  { --primary:#c2410c; --primary-foreground:#ffffff; --ring:#c2410c; --accent:#ffece0; --accent-foreground:#7c2d12;
                 --sidebar-primary:#c2410c; --sidebar-primary-foreground:#ffffff; --sidebar-ring:#c2410c; --sidebar-accent:#ffece0; --sidebar-accent-foreground:#7c2d12; }
.theme-amethyst{ --primary:#7c3aed; --primary-foreground:#ffffff; --ring:#7c3aed; --accent:#f2e9fe; --accent-foreground:#5b21b6;
                 --sidebar-primary:#7c3aed; --sidebar-primary-foreground:#ffffff; --sidebar-ring:#7c3aed; --sidebar-accent:#f2e9fe; --sidebar-accent-foreground:#5b21b6; }
/* Marigold: DARK text on the yellow primary (white on yellow is unreadable). */
.theme-marigold{ --primary:#eab308; --primary-foreground:#1c1917; --ring:#ca8a04; --accent:#fef7cd; --accent-foreground:#713f12;
                 --sidebar-primary:#eab308; --sidebar-primary-foreground:#1c1917; --sidebar-ring:#ca8a04; --sidebar-accent:#fef7cd; --sidebar-accent-foreground:#713f12; }

/* ── Integral Electric — cyan on a dark base ───────────────────────────── */
.theme-integral {
  color-scheme: dark;
  --background:#08191d; --foreground:#d7eef2;
  --card:#0f2429; --card-foreground:#d7eef2;
  --popover:#0f2429; --popover-foreground:#d7eef2;
  --muted:#163137; --muted-foreground:#7fa6ad;
  --border:#21454c; --border-subtle:#153036; --input:#21454c;
  --surface-inset:#0a2025;
  --accent:#10323a; --accent-foreground:#a5eef7;
  --primary:#22d3ee; --primary-foreground:#05252c; --ring:#22d3ee;
  --sidebar:#0f2429; --sidebar-foreground:#d7eef2; --sidebar-border:#21454c;
  --sidebar-primary:#22d3ee; --sidebar-primary-foreground:#05252c;
  --sidebar-accent:#163137; --sidebar-accent-foreground:#d7eef2; --sidebar-ring:#22d3ee;
  --success:#5fd39a; --success-hard:#22c55e;
  --warning:#e3c45e;
  --destructive:#f87171; --destructive-hard:#ef4444;
  --info:#22d3ee;
}

/* ── Base layout ───────────────────────────────────────────────────────── */
* { box-sizing: border-box; }
body {
  font-family: -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; margin: 0;
  background: var(--background); color: var(--foreground); font-size: 14px;
  min-height: 100vh;
}
/* The chosen screen font (--ui-font) applies to the content column only, so the
   sidebar keeps the default UI font. Set via nav.js (app-font). */
.content { font-family: var(--ui-font, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif); }

/* Screen font, chosen in Settings. One class per option on <html>, mirroring how
   theme-* and finish-* work. This used to be a <style> element that nav.js built
   and injected; style-src 'self' refuses those, and there is no nonce available
   on a static Pages deploy. 'default' has no class — it just leaves --ui-font
   unset so the fallback in .content applies. */
html.font-system { --ui-font: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }
html.font-calibri { --ui-font: Calibri, "Segoe UI", sans-serif; }
html.font-verdana { --ui-font: Verdana, Geneva, sans-serif; }
html.font-tahoma { --ui-font: Tahoma, Geneva, sans-serif; }
html.font-trebuchet { --ui-font: "Trebuchet MS", Verdana, sans-serif; }
html.font-georgia { --ui-font: Georgia, "Times New Roman", serif; }
html.font-cambria { --ui-font: Cambria, Georgia, serif; }
html.font-times { --ui-font: "Times New Roman", Times, serif; }
html.font-consolas { --ui-font: Consolas, "Cascadia Code", Menlo, monospace; }

/* Geist, served from this origin.
 *
 * The content security policy is font-src 'self', so a Google Fonts link would
 * be refused by the browser rather than merely discouraged. That is the policy
 * working: the portal fetches nothing from anywhere else. So the file is served
 * from public/fonts alongside its licence, which the SIL Open Font License
 * requires to travel with it.
 *
 * One variable file covers every weight, which is why it is 68 KB rather than
 * the six static files it replaces. swap, so text is readable in the fallback
 * face while the font arrives and nothing is invisible on a slow connection.
 *
 * The stack keeps a real fallback after it. A theme that renders nothing when
 * one file 404s is worse than one that renders in Segoe UI. */
@font-face {
  font-family: "Geist";
  /* format("woff2"), not format("woff2-variations"). The latter was an interim
     value that CSS Fonts 4 replaced, and the rule for an unrecognised format
     string is that the browser must skip that src entirely. There is only one
     src here, so a browser that does not know the old spelling has nothing to
     fall back to and quietly renders in Segoe UI: the font dropdown appears to
     do nothing, with no console error and no network request to explain it.
     Plain woff2 loads a variable font correctly everywhere that supports
     variable fonts at all, and font-weight below is what declares the range. */
  src: url("/fonts/geist-variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
html.font-geist { --ui-font: "Geist", -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; }

/* ── Paper Amber ─────────────────────────────────────────────────────────
 *
 * A white paper ground, hairline rules, and amber as the single accent.
 *
 * Named for what it looks like rather than for where it came from. It was
 * measured from the sister RFP portal at C:\dev\rfp-portal, and that is worth
 * recording for anyone who has to keep the two in step, but the name of another
 * product does not belong in a picker on a client's screen.
 *
 * Measured rather than guessed at: that palette is almost
 * entirely achromatic, neutral-500 and neutral-900 accounting for most of its
 * text, with amber as the one real accent and emerald reserved for success.
 * Nearly every surface is rounded-lg over a hairline neutral-200 border, and
 * shadow is close to absent. So the character of it is as much the geometry and
 * the restraint as the colours, which is why the radii above became tokens: a
 * palette alone would have produced those colours on this portal's shapes.
 *
 * Light, where this portal defaults dark. color-scheme is set so form controls,
 * scrollbars and the caret follow, which is the detail that otherwise gives a
 * light theme away the moment somebody clicks into a field.
 *
 * The accent is amber rather than the blue every other theme here uses, and it
 * is deliberately the same amber that portal uses for its own emphasis. --info
 * stays blue: it is the expat/national distinction on the register, it means
 * something on its own, and a theme is not the place to redefine it. */
.theme-paperamber {
  color-scheme: light;

  --background: #ffffff;     --foreground: #171717;
  --card: #ffffff;           --card-foreground: #171717;
  --popover: #ffffff;        --popover-foreground: #171717;
  --muted: #fafafa;          --muted-foreground: #737373;
  --border: #e5e5e5;         --border-subtle: #f5f5f5;   --input: #d4d4d4;
  --surface-inset: #fafafa;

  --primary: #b45309;        --primary-foreground: #ffffff;
  --accent: #fffbeb;         --accent-foreground: #78350f;
  --ring: #b45309;

  --sidebar: #fafafa;        --sidebar-foreground: #404040;
  --sidebar-border: #e5e5e5;
  --sidebar-primary: #b45309; --sidebar-primary-foreground: #ffffff;
  --sidebar-accent: #f5f5f5;  --sidebar-accent-foreground: #171717;
  --sidebar-ring: #b45309;

  --success: #047857;        --success-hard: #059669;
  --warning: #b45309;
  --destructive: #b91c1c;    --destructive-hard: #dc2626;
  --info: #1d4ed8;

  /* The geometry, stated rather than inherited. These are the same three values
     the default theme uses, which is not an oversight: the look being copied is
     built on an 8px radius and so is this portal, so the shapes already agreed
     and inventing a difference to prove the tokens work would be worse than
     admitting they match. They are written out because a theme that names its
     geometry cannot drift when the default changes, and because this is the
     block somebody edits to reshape it. What is flatter is the shadow below,
     which is the real geometric difference between the two designs. */
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --shadow-card: 0 1px 2px rgba(0, 0, 0, .04);
}

/* Two-column layout only once nav.js has inserted the sidebar. Pages without it
   (e.g. chevron.html) stay single-column, and there's no pre-restructure flash. */
body:has(.sidebar) { display: flex; }
a { color: var(--primary); text-decoration: none; }

.content { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

header { padding: 18px 24px; border-bottom: 1px solid var(--border); display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; }
header h1 { margin: 0; font-size: 18px; font-weight: 700; letter-spacing: -0.01em; }
header .sub { color: var(--muted-foreground); font-size: 12.5px; padding-left: 14px; border-left: 1px solid var(--border); }
.screen-help { margin-left: auto; align-self: center; flex: 0 0 auto; width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--radius-pill); border: 1px solid var(--border); color: var(--muted-foreground); font-size: 13px; font-weight: 700; text-decoration: none; }
.screen-help:hover { border-color: var(--primary); color: var(--primary); }
/* The sidebar already carries "Sercom Oil / CMS Personnel Portal", so the page
   header repeated the brand on every screen and spent about 60px of vertical
   space saying it a second time.
   Scoped to .content, which only nav.js creates, so the four pages with no
   sidebar (login, reset, chevron, travel-request) keep their header as the only
   branding they have.
   Hidden rather than deleted from the 24 pages: nav.js anchors on <header> and
   returns early when there is not one, so removing the element would take the
   whole sidebar with it. */
.content > header { display: none; }

/* About panel, opened from the "i" in the sidebar brand (nav.js). */
.about-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.55); display: flex; align-items: center; justify-content: center; z-index: 80; padding: 16px; }
.about-card { background: var(--card); color: var(--card-foreground); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 22px 24px; width: min(520px, 100%); max-height: 86vh; overflow: auto; }
.about-card h2 { margin: 0 0 10px; font-size: 17px; }
.about-card p { margin: 0 0 10px; font-size: 13px; line-height: 1.6; }
.about-card .about-ip { color: var(--muted-foreground); font-size: 12px; }
.about-dl { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; margin: 16px 0 0; font-size: 13px; }
.about-dl dt { color: var(--muted-foreground); }
.about-dl dd { margin: 0; font-variant-numeric: tabular-nums; word-break: break-all; }
.about-actions { display: flex; justify-content: flex-end; margin-top: 18px; }
.about-close { background: var(--border); color: var(--foreground); border: 0; border-radius: var(--radius-md); padding: 7px 13px; font: inherit; font-weight: 600; cursor: pointer; }

/* Shown in place of the whole screen while access is suspended (nav.js). */
.suspended-notice { border-color: color-mix(in srgb, var(--destructive-hard) 45%, var(--border)); max-width: 640px; }
.suspended-notice h2 { color: var(--destructive); margin-top: 0; }

main { padding: 22px 24px; }

/* ── Sidebar (built by nav.js) ─────────────────────────────────────────── */
.sidebar {
  flex: 0 0 236px; width: 236px;
  position: sticky; top: 0; align-self: flex-start; height: 100vh;
  display: flex; flex-direction: column;
  background: var(--sidebar); color: var(--sidebar-foreground);
  border-right: 1px solid var(--sidebar-border);
}
/* No width transition: it is a higher cascade origin than !important and would
   fight the collapsed rail's fixed width. Collapse snaps; drag tracks live. */
.sidebar-brand { position: relative; padding: 15px 16px; border-bottom: 1px solid var(--sidebar-border); display: flex; align-items: flex-start; gap: 8px; }
.sidebar-brand .txt { flex: 1 1 auto; min-width: 0; }
.sidebar-brand h1 { margin: 0; font-size: 15px; line-height: 1.25; white-space: nowrap; }
.sidebar-brand .sub { display: block; margin-top: 3px; color: var(--muted-foreground); font-size: 11px; white-space: nowrap; }
.sidebar-collapse-btn { flex: 0 0 auto; background: transparent; border: 0; color: var(--sidebar-foreground); cursor: pointer; padding: 4px; margin: -2px -4px 0 0; border-radius: var(--radius-sm); opacity: .65; }
.sidebar-collapse-btn:hover { background: var(--sidebar-accent); color: var(--sidebar-accent-foreground); opacity: 1; }
.sidebar-collapse-btn svg { width: 16px; height: 16px; display: block; transition: transform .18s ease; }

/* Drag-to-resize handle on the sidebar's right edge (desktop only). */
.sidebar-resize { position: absolute; top: 0; right: 0; width: 6px; height: 100%; cursor: col-resize; z-index: 30; }
.sidebar-resize:hover { background: color-mix(in srgb, var(--sidebar-primary) 45%, transparent); }
.sidebar nav { flex: 1 1 auto; overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 2px; }
.sidebar nav a {
  display: flex; align-items: center; gap: 10px; padding: 8px 11px;
  border-radius: var(--radius-md); color: var(--sidebar-foreground); font-size: 13px; line-height: 1;
  transition: background .12s ease, color .12s ease;
}
.sidebar nav a svg { width: 16px; height: 16px; flex: 0 0 16px; opacity: .85; }
.sidebar nav a:hover { background: var(--sidebar-accent); color: var(--sidebar-accent-foreground); }
.sidebar nav a.active { background: var(--sidebar-primary); color: var(--sidebar-primary-foreground); font-weight: 600; }
.sidebar nav a.active svg { opacity: 1; }
.sidebar-foot { border-top: 1px solid var(--sidebar-border); padding: 10px; display: flex; flex-direction: column; gap: 8px; position: relative; }
.sidebar-foot input[type=search] {
  background: var(--card); border: 1px solid var(--border); color: var(--foreground);
  font: inherit; font-size: 13px; padding: 7px 10px; border-radius: var(--radius-md); width: 100%;
}
/* Account chip (bottom-left) + its popup, in the style of Boko's user menu. */
.sidebar-account { position: relative; }
.account-btn {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: transparent; border: 0; color: var(--sidebar-foreground);
  font: inherit; padding: 6px 8px; border-radius: var(--radius-md); cursor: pointer; text-align: left;
}
.account-btn:hover { background: var(--sidebar-accent); color: var(--sidebar-accent-foreground); }
.account-btn .avatar {
  position: relative; flex: 0 0 28px; width: 28px; height: 28px; border-radius: var(--radius-pill);
  display: inline-flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700;
  background: var(--sidebar-primary); color: var(--sidebar-primary-foreground);
}
.account-btn .account-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.account-btn .account-dot { position: absolute; top: -2px; right: -2px; width: 9px; height: 9px; border-radius: var(--radius-pill); background: var(--sidebar-primary); border: 2px solid var(--sidebar); }

.account-pop {
  position: absolute; left: 8px; right: 8px; bottom: calc(100% + 6px);
  background: var(--popover); color: var(--popover-foreground);
  border: 1px solid var(--border); border-radius: var(--radius-md); padding: 6px;
  box-shadow: 0 12px 34px -8px rgba(0,0,0,.5); z-index: 70;
}
.account-pop .account-email { font-size: 11px; color: var(--muted-foreground); padding: 6px 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-pop .sep { height: 1px; background: var(--border); margin: 4px 2px; }
.account-item { display: flex; align-items: center; gap: 8px; padding: 7px 8px; border-radius: var(--radius-sm); color: inherit; font-size: 12.5px; text-decoration: none; }
.account-item:hover { background: var(--accent); color: var(--accent-foreground); }
.account-item svg { width: 15px; height: 15px; flex: 0 0 15px; }
.account-item .dot { width: 7px; height: 7px; border-radius: var(--radius-pill); background: var(--primary); margin-left: auto; }

/* Appearance controls (Theme + Display Style), rendered on the Settings page. */
.appr .grp { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--muted-foreground); padding: 10px 4px 4px; }
.appr .opt {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: transparent; border: 0; color: inherit; font: inherit; font-size: 13px;
  padding: 7px 8px; border-radius: var(--radius-sm); cursor: pointer; text-align: left;
}
.appr .opt:hover { background: var(--accent); color: var(--accent-foreground); }
.appr .opt .sw { width: 16px; height: 16px; flex: 0 0 16px; border-radius: var(--radius-sm); border: 1px solid var(--border); }
.appr .opt .lbl { flex: 1 1 auto; }
.appr .opt .tick { width: 16px; flex: 0 0 16px; color: var(--primary); opacity: 0; }
.appr .opt.sel .tick { opacity: 1; }
.appr .sep { height: 1px; background: var(--border); margin: 6px 2px; }
.appr .fontsel { width: 100%; background: var(--card); color: var(--foreground); border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: 13px; padding: 7px 8px; margin: 2px 0 4px; cursor: pointer; }
.appr .fontsel:focus { outline: 0; border-color: var(--primary); }
/* The native option list renders on a white popup regardless of theme, so pin
   the option text dark (light --foreground would be invisible on it). */
.appr .fontsel option { color: #1a1a1a; background: #ffffff; }

/* Advanced (custom colours) builder inside the appearance controls. */
.appr .opt.adv-toggle .sw-adv { display: inline-flex; align-items: center; justify-content: center; color: var(--muted-foreground); border: 0; }
.appr .opt.adv-toggle .sw-adv svg { width: 15px; height: 15px; }
.appr .adv[hidden] { display: none; }
.appr .adv { padding: 2px 4px 4px; }
.appr .cprev { display: flex; height: 50px; border: 1px solid var(--border); border-radius: var(--radius-md); overflow: hidden; margin: 4px 2px 8px; }
.appr .cprev-side { width: 34%; background: var(--sidebar); }
.appr .cprev-main { flex: 1 1 auto; background: var(--card); display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 0 10px; }
.appr .cprev-tt { color: var(--foreground); font-size: 13px; font-weight: 600; }
.appr .cprev-btn { background: var(--primary); color: var(--primary-foreground); font-size: 11px; font-weight: 600; padding: 4px 8px; border-radius: var(--radius-sm); }
.appr .crow { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 12px; color: var(--muted-foreground); padding: 4px 4px; }
.appr .crow input[type=color] { width: 34px; height: 22px; padding: 0; border: 1px solid var(--border); border-radius: var(--radius-sm); background: transparent; cursor: pointer; }
.appr .crow select { background: var(--card); color: var(--foreground); border: 1px solid var(--border); border-radius: var(--radius-sm); font: inherit; font-size: 12px; padding: 4px 6px; }
.appr .cwarn { font-size: 11px; color: var(--warning); padding: 4px 6px; line-height: 1.4; }
.appr .cacts { display: flex; gap: 6px; padding: 4px 2px 2px; }
.appr .cbtn { flex: 1 1 auto; font: inherit; font-size: 12px; font-weight: 600; padding: 6px 8px; border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--card); color: var(--foreground); cursor: pointer; }
.appr .cbtn:hover { background: var(--accent); }
.appr .cbtn-primary { background: var(--primary); color: var(--primary-foreground); border-color: var(--primary); }

/* Palette trigger at the top of the sidebar + its dropdown. */
.sidebar-appr { flex: 0 0 auto; }
.sidebar-appr-btn { background: transparent; border: 0; color: var(--sidebar-foreground); cursor: pointer; padding: 4px; margin-top: -2px; border-radius: var(--radius-sm); opacity: .65; }
.sidebar-appr-btn:hover { background: var(--sidebar-accent); color: var(--sidebar-accent-foreground); opacity: 1; }
.sidebar-appr-btn svg { width: 16px; height: 16px; display: block; }
.appearance-pop {
  position: absolute; left: 8px; right: 8px; top: calc(100% + 6px);
  max-height: 76vh; overflow-y: auto;
  background: var(--popover); color: var(--popover-foreground);
  border: 1px solid var(--border); border-radius: var(--radius-md); padding: 6px;
  box-shadow: 0 14px 36px -8px rgba(0,0,0,.5); z-index: 80;
}

/* Mobile sidebar toggle + backdrop (created by nav.js) */
.sidebar-toggle {
  display: none; position: fixed; top: 10px; left: 10px; z-index: 65;
  width: 38px; height: 38px; align-items: center; justify-content: center;
  background: var(--card); color: var(--foreground); border: 1px solid var(--border);
  border-radius: var(--radius-md); cursor: pointer;
}
.sidebar-backdrop { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 55; }

/* Collapsed rail — icons only, labels hidden (desktop). */
@media (min-width: 821px) {
  .sidebar.collapsed { width: 60px !important; flex-basis: 60px !important; }
  .sidebar.collapsed .sidebar-brand { justify-content: center; padding-left: 0; padding-right: 0; }
  .sidebar.collapsed .sidebar-brand .txt { display: none; }
  .sidebar.collapsed .sidebar-appr { display: none; }
  /* Collapsed leaves only the toggle, which is the existing intent for the
     appearance control directly above. About follows it rather than being the
     one icon that survives. */
  .sidebar.collapsed .sidebar-info { display: none; }
  .sidebar.collapsed .sidebar-collapse-btn { margin: 0; }
  .sidebar.collapsed .sidebar-collapse-btn svg { transform: rotate(180deg); }
  .sidebar.collapsed nav a { justify-content: center; padding-left: 0; padding-right: 0; }
  .sidebar.collapsed nav a span { display: none; }
  .sidebar.collapsed .sidebar-foot input[type=search] { display: none; }
  .sidebar.collapsed .account-btn { justify-content: center; padding-left: 0; padding-right: 0; }
  .sidebar.collapsed .account-btn .account-name { display: none; }
  .sidebar.collapsed .sidebar-resize { display: none; }
  /* Popup can't fit in the rail — fly it out to the right. */
  .sidebar.collapsed .account-pop { left: calc(100% + 6px); right: auto; width: 220px; bottom: 8px; }
}

/* ── Cards & content ───────────────────────────────────────────────────── */
/* One elevation recipe, shared by tiles/panels/tablewrap: a faint top inset
   (reads as a highlight on dark, a hairline on light — same technique the
   Glass finish uses) plus a soft, wide, low shadow. Subtle by design so it
   still reads as "flat admin surface", not a marketing card. */
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; margin-bottom: 22px; }
.tile {
  border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 14px 16px;
  background: var(--card); color: var(--card-foreground);
  box-shadow: var(--shadow-card);
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
a.tile:hover {
  transform: translateY(-1px);
  border-color: color-mix(in srgb, var(--primary) 45%, var(--border));
  box-shadow: var(--shadow-card);
}
.tile .n { font-size: 27px; font-weight: 800; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; line-height: 1.1; }
.tile .l { color: var(--muted-foreground); font-size: 12px; margin-top: 3px; }

.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 820px) { .grid2 { grid-template-columns: 1fr; } }

.panel {
  border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--card); color: var(--card-foreground); margin-bottom: 16px;
  box-shadow: var(--shadow-card);
}
.panel h2 { margin: 0; font-size: 14px; font-weight: 700; letter-spacing: -0.003em; color: var(--card-foreground); padding: 13px 16px; border-bottom: 1px solid var(--border); }
.panel .body { padding: 8px 16px 14px; }
.panel.red h2 { color: var(--destructive); }
.panel.amber h2 { color: var(--warning); }

.row { display: flex; justify-content: space-between; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--border-subtle); font-size: 13px; transition: background .12s ease; }
.row:last-child { border-bottom: 0; }
.row .meta { color: var(--muted-foreground); font-size: 12px; font-variant-numeric: tabular-nums; }
.muted { color: var(--muted-foreground); }

/* A page's initial "Loading…" text (id="loading" is the shared convention
   across every screen) breathes gently instead of sitting inert. */
#loading { animation: loading-breathe 1.6s ease-in-out infinite; }
@keyframes loading-breathe { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }

table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
th, td { text-align: left; padding: 7px 8px; border-bottom: 1px solid var(--border-subtle); vertical-align: top; }
th { position: sticky; top: 0; background: var(--muted); color: var(--muted-foreground); font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: .03em; }
tr { transition: background .12s ease; }
tr:hover td { background: var(--accent); }
.tablewrap {
  border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: auto; max-height: calc(100vh - 150px);
  box-shadow: var(--shadow-card);
}

input.cell, select.cell {
  background: transparent; border: 1px solid transparent; color: var(--foreground);
  font: inherit; padding: 3px 4px; border-radius: var(--radius-sm); width: 100%; min-width: 70px;
  transition: border-color .12s ease, background .12s ease;
}
input.cell:hover, select.cell:hover { border-color: var(--input); }
input.cell:focus, select.cell:focus { border-color: var(--ring); background: var(--surface-inset); outline: none; }
td.saved input.cell, td.saved select.cell { border-color: color-mix(in srgb, var(--success-hard) 55%, transparent); }

.pill { display: inline-block; padding: 1px 7px; border-radius: var(--radius-pill); font-size: 11px; font-weight: 600; }
.s-accepted { background: color-mix(in srgb, var(--success-hard) 24%, transparent); color: var(--success); }
.s-declined { background: color-mix(in srgb, var(--destructive-hard) 24%, transparent); color: var(--destructive); }
.s-pending  { background: color-mix(in srgb, var(--warning) 22%, transparent); color: var(--warning); }
.s-other    { background: color-mix(in srgb, var(--muted-foreground) 20%, transparent); color: var(--foreground); }
.t-expat    { color: var(--info); }
.t-national { color: var(--success); }
/* No type recorded. The warning colour rather than the muted one: this is not an
   optional detail left blank, it is a person the compliance rules cannot be
   applied to. */
.t-unset    { color: var(--warning); font-style: italic; }

.certs { display: flex; gap: 3px; flex-wrap: wrap; width: 72px; }  /* 3 chips per row (3×22 + 2×3 gap) */
.cert { width: 22px; height: 20px; border-radius: var(--radius-sm); font-size: 10px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; }
.c-valid   { background: color-mix(in srgb, var(--success-hard) 24%, transparent); color: var(--success); }
.c-tbd     { background: color-mix(in srgb, var(--muted-foreground) 22%, transparent); color: var(--muted-foreground); }
.c-expired { background: color-mix(in srgb, var(--destructive-hard) 34%, transparent); color: var(--destructive); }
.c-na      { background: color-mix(in srgb, var(--success-hard) 24%, transparent); color: var(--success); }  /* not applicable = clear (green) */
.c-missing { background: color-mix(in srgb, var(--warning) 22%, transparent); color: var(--warning); }

.visa-bad  { color: var(--destructive); font-weight: 600; }
.visa-soon { color: var(--warning); font-weight: 600; }
/* The positive counterpart of the two above, for a dashboard tile that is good
   news. The status pill classes (.s-accepted and friends) look right in a table
   cell and wrong on a tile number — they carry a filled background, so "16
   Ready to deploy" rendered as a green bar rather than a green number. */
.count-ok  { color: var(--success); font-weight: 600; }

/* ── Mobile / phones ───────────────────────────────────────────────────── */
@media (max-width: 820px) {
  body:has(.sidebar) { display: block; }   /* drawer, not a column, on phones */
  .sidebar {
    position: fixed; left: 0; top: 0; height: 100vh;
    width: 260px !important; flex-basis: 260px !important;   /* ignore the persisted desktop px */
    transform: translateX(-100%); transition: transform .25s ease; z-index: 60;
    box-shadow: 0 0 40px rgba(0,0,0,.5);
  }
  .sidebar.collapsed { width: 260px !important; flex-basis: 260px !important; }  /* collapse is a desktop concept */
  .sidebar.open { transform: none; }
  .sidebar.open ~ .sidebar-backdrop { display: block; }
  .sidebar-resize { display: none; }                 /* no edge-drag on the mobile drawer */
  .sidebar-toggle { display: inline-flex; }
  .content { padding-top: 4px; }
  header { padding: 12px 14px 12px 56px; gap: 6px 12px; }
  header h1 { font-size: 15px; }
  main { padding: 14px; }
  /* The header used to reserve the space the fixed hamburger sits in (its 56px
     left padding above). With the header hidden, the first line of every screen
     would start underneath it, so the content keeps clear of it here instead. */
  .content > main { padding-top: 52px; }
  .tablewrap { max-height: none; -webkit-overflow-scrolling: touch; }
  .tiles { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 8px; }
  .tile { padding: 12px 13px; }
  .tile .n { font-size: 22px; }
}

/* ============================================================================
   DISPLAY STYLES (finishes) — unlayered, so they override the token-based
   surface backgrounds above. Scoped to cards + the sidebar ONLY (never table
   rows / long lists — backdrop-blur on hundreds of rows is a perf problem).
   Cards are matched by their stable classes (.panel/.tile) and by
   [data-slot="card"]; the sidebar by [data-slot="sidebar"].
   ========================================================================== */

/* ── Frosted Glass ─────────────────────────────────────────────────────── */
.finish-glass .panel,
.finish-glass .tile,
.finish-glass [data-slot="card"] {
  background: color-mix(in srgb, var(--card) 55%, transparent);
  border: 1px solid color-mix(in srgb, var(--foreground) 12%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  backdrop-filter: blur(14px) saturate(1.4);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--foreground) 12%, transparent),
    0 12px 28px -16px rgba(0, 0, 0, 0.32);
}
.finish-glass [data-slot="sidebar"] {
  background: color-mix(in srgb, var(--sidebar) 62%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(1.35);
  backdrop-filter: blur(18px) saturate(1.35);
  box-shadow: inset -1px 0 0 color-mix(in srgb, var(--foreground) 8%, transparent);
}

/* ── Ink & Bevel ───────────────────────────────────────────────────────── */
.finish-ink [data-slot="sidebar"] {
  background: linear-gradient(180deg, #0c0d0f 0%, #17181b 55%, #101114 100%);
  border-right-color: #000000;
  box-shadow: inset -1px 0 0 rgba(255, 255, 255, 0.06);
  /* THE FIX: set colour DIRECTLY, not only the token — inherited nav text
     (brand title, labels with no colour class) is computed from the OUTER
     --foreground and would otherwise stay dark-on-dark = invisible. */
  color: #f2f4f7;
  /* Re-map tokens within the sidebar so any element that DOES use a colour
     utility flips to light-on-dark regardless of the active theme. */
  --foreground: #f2f4f7;
  --card-foreground: #f2f4f7;
  --muted-foreground: #9aa1a9;
  --muted: rgba(255, 255, 255, 0.07);
  --accent: rgba(255, 255, 255, 0.08);
  --accent-foreground: #ffffff;
  --border: #2b2f35;
  --border-subtle: #2b2f35;
  --popover: #17181b;
  --popover-foreground: #f2f4f7;
  --primary: #a5b4fc;
  --ring: #a5b4fc;
  --sidebar-foreground: #f2f4f7;
  --sidebar-border: #2b2f35;
  --sidebar-accent: rgba(255, 255, 255, 0.08);
  --sidebar-accent-foreground: #ffffff;
  --sidebar-primary: #a5b4fc;
  --sidebar-primary-foreground: #0b1220;
  --sidebar-ring: #a5b4fc;
}
.finish-ink .panel,
.finish-ink .tile,
.finish-ink [data-slot="card"] {
  border: 0.75px solid var(--foreground);
  border-radius: var(--radius-md);
  box-shadow: 0 2px 0 rgba(0, 0, 0, 0.45);
}

/* ── Save failure, focus and skip link ──────────────────────────────────────
   A field whose edit did not save stays marked until it is dealt with. The
   outline is backed by aria-invalid in save-status.js so the state is not
   carried by colour alone. */
.save-failed {
  outline: 2px solid var(--destructive-hard);
  outline-offset: -1px;
  background: color-mix(in srgb, var(--destructive-hard) 8%, transparent);
}

/* The bar that says what failed and offers to send it again. */
.save-bar {
  position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%);
  z-index: 200; max-width: min(680px, calc(100vw - 32px));
  display: flex; align-items: center; gap: 12px;
  background: var(--card); color: var(--foreground);
  border: 1px solid var(--destructive-hard); border-left-width: 4px;
  border-radius: var(--radius-md); padding: 11px 14px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .35);
  font-size: 13.5px; line-height: 1.45;
}
.save-bar-text { flex: 1; }
.save-bar-btn {
  flex: none; font: inherit; font-weight: 600; font-size: 12.5px;
  padding: 6px 12px; border-radius: var(--radius-sm); cursor: pointer;
  background: var(--primary); color: var(--primary-foreground); border: 0;
}
.save-bar-btn:disabled { opacity: .6; cursor: default; }
.save-bar-dismiss { background: var(--surface-inset); color: var(--muted-foreground); }

/* A control with a request in flight, set by whileBusy() in save-status.js. A
   real <button> is also given the disabled property, but half the controls this
   covers are <span class="actlink">, where disabled means nothing — so the
   pointer is turned off here as well, and the control fades so it is obvious
   the click was taken and is still going. */
[data-busy] { opacity: .55; pointer-events: none; cursor: default; }

/* Announcements for assistive tech only. Not display:none — that would stop it
   being read out. */
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* A visible focus ring for keyboard users. :focus-visible so it does not appear
   on mouse clicks. There was almost none of this before, which made the portal
   difficult to use without a mouse. */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Skip past the sidebar, which is the same 15 links on every screen. Visible
   only once focused. */
.skip-link {
  position: absolute; left: 8px; top: -48px; z-index: 300;
  background: var(--primary); color: var(--primary-foreground);
  padding: 9px 14px; border-radius: var(--radius-md); text-decoration: none; font-size: 13px;
  transition: top .12s ease;
}
.skip-link:focus { top: 8px; }
