﻿/* Udayan Online Billing — Module 1 UI. One shared stylesheet for the whole module.
   Vanilla CSS, no build, no framework, no CDN — same discipline as the map's
   public/ pages (portal.html, devices.html). The palette blends the platform's
   house green-teal (--sn-header #0b5d4e, --sn-accent #17a67d) with the maXim
   commercial-panel teal so the panel reads as Udayan Online, not a clone. */

:root {
  /* dark navy sidebar, the way the operator's reference dashboard has it */
  /* ── the rail, restyled 2026-08-25 ──────────────────────────────────────
     Was a "horizon": a navy-to-violet gradient with glowing raised pills. The
     operator asked for the quiet, flat treatment ChatGPT uses instead, and the
     reason it works is that a sidebar is scenery — it is read once to find a
     page and then ignored. Every gradient and glow it carries is contrast
     spent on the part of the screen nobody came for.
     One near-black ground, one barely-there hover, one flat active fill. */
  --sn-side:        #181818;
  --sn-side-2:      #181818;   /* brand block: same ground, no seam */
  --sn-side-ink:    #ececec;   /* menu label */
  --sn-side-muted:  #8f8f8f;   /* section headings, secondary rows */
  --sn-side-hover:  #ffffff14;
  --sn-side-active-bg: #ffffff1f;

  /* the blue the reference dashboard is built on */
  --sn-header:      #ffffff;   /* top bar — white, with dark ink */
  --sn-header-ink:  #1e293b;
  --sn-primary:     #2563eb;   /* buttons, active pill */
  --sn-primary-dk:  #1d4ed8;
  --sn-accent:      #3b82f6;   /* lighter blue, for the active bar */
  --sn-teal:        #0ea5e9;   /* sky, for links/accents */
  --sn-up:          #16a34a;   /* the "↑ from last month" green */

  --sn-page:        #f5f7fb;
  --sn-card:        #ffffff;
  --sn-ink:         #1e293b;
  --sn-ink-soft:    #475569;
  --sn-muted:       #8b98ad;
  --sn-line:        #e8edf5;
  --sn-line-soft:   #f1f4f9;
  --sn-unknown:     #b6bfcb;   /* the dash colour — "could not measure" */
  --sn-focus:       #2563eb;

  --sn-radius:      14px;
  --sn-radius-sm:   10px;
  --sn-shadow: 0 1px 2px rgba(16,24,40,.04), 0 1px 3px rgba(16,24,40,.06);
  --sn-shadow-lg: 0 10px 34px rgba(16,24,40,.16);

  /* pastel icon discs. Each is a tint of its own hue, not of the accent, so a
     card's icon says which KPI it is at a glance. */
  --ic-violet-bg:#ede9fe; --ic-violet-ink:#7c3aed;
  --ic-green-bg: #dcfce7; --ic-green-ink: #16a34a;
  --ic-amber-bg: #ffedd5; --ic-amber-ink: #ea580c;
  --ic-rose-bg:  #ffe4e6; --ic-rose-ink:  #e11d48;
  --ic-blue-bg:  #dbeafe; --ic-blue-ink:  #2563eb;
  --ic-sky-bg:   #e0f2fe; --ic-sky-ink:   #0284c7;
  --ic-teal-bg:  #ccfbf1; --ic-teal-ink:  #0d9488;
  --ic-slate-bg: #e2e8f0; --ic-slate-ink: #475569;

  --sn-side-w:      262px;

  /* status hues (paired bg/ink; the pill always carries its word too, so
     colour is never the only signal — WCAG) */
  --st-ok-bg:#dcfce7;      --st-ok-ink:#15803d;
  --st-free-bg:#dbeafe;    --st-free-ink:#1d4ed8;
  --st-online-bg:#ccfbf1;  --st-online-ink:#0f766e;
  --st-unverified-bg:#fef3c7; --st-unverified-ink:#92650e;
  --st-grace-bg:#fef3c7;   --st-grace-ink:#92650e;
  --st-unpaid-bg:#ffedd5;  --st-unpaid-ink:#c2410c;
  --st-expired-bg:#ffe4e6; --st-expired-ink:#be123c;
  --st-expunl-bg:#ede9fe;  --st-expunl-ink:#6d28d9;
  --st-locked-bg:#fee2e2;  --st-locked-ink:#b91c1c;
  --st-nonid-bg:#fecaca;   --st-nonid-ink:#991b1b;
  --st-disabled-bg:#e2e8f0;--st-disabled-ink:#475569;

  /* chart series hues — both ≥4.5:1 on the white card, and distinguishable to
     the common colour-vision deficiencies (blue vs. orange, not red vs. green).
     The legend spells every series out regardless. */
  --ct-blue:   #1f6bb0;
  --ct-orange: #c05621;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
body {
  background: var(--sn-page);
  color: var(--sn-ink);
  font: 14px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
        "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
button { font: inherit; }

/* Visible focus everywhere — keyboard navigability is non-negotiable. */
:focus-visible {
  outline: 2px solid var(--sn-focus);
  outline-offset: 2px;
  border-radius: 3px;
}
.sn-skip {
  position: absolute; left: -999px; top: 8px; z-index: 100;
  background: #fff; color: var(--sn-ink); padding: 8px 14px; border-radius: 6px;
  box-shadow: var(--sn-shadow);
}
.sn-skip:focus { left: 12px; }

/* Visible to a screen reader, not to the eye. Used where a colour-only glyph
   (the online lamp) needs its meaning spelled out in text. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── layout ────────────────────────────────────────────────────────────── */
.sn-shell { display: flex; min-height: 100vh; }

/* ── sidebar ───────────────────────────────────────────────────────────── */
/* One flat ground, no gradient, no lit edges. The only thing separating the
   rail from the page is a hairline — the rail earns its separation by being a
   different tone, not by being a different material. */
.sn-side {
  width: var(--sn-side-w); flex: none;
  background: var(--sn-side);
  color: var(--sn-side-ink);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
  border-right: 1px solid #ffffff0f;
  /* The rail scrolls often and is not the subject: hide the bar until the
     pointer is actually in it. */
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
}
.sn-side:hover { scrollbar-color: #ffffff26 transparent; }
.sn-side::-webkit-scrollbar { width: 8px; }
.sn-side::-webkit-scrollbar-thumb { background: transparent; border-radius: 4px; }
.sn-side:hover::-webkit-scrollbar-thumb { background: #ffffff1f; }

/* Holds the collapse control and nothing else now that the wordmark is gone,
   so it is sized for a button rather than for a lockup. Same ground as the
   rail: no seam, no shadow, no header bar. */
.sn-brand {
  display: flex; align-items: center;
  padding: 6px 8px 2px; min-height: 40px;
  background: var(--sn-side);
  position: relative; z-index: 1;
}
.sn-brand-mark {
  width: 34px; height: 34px; border-radius: 10px; flex: none;
  background: linear-gradient(135deg, var(--sn-accent), var(--sn-teal));
  color: #fff; font-weight: 800; font-size: 14px; letter-spacing: .5px;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.14);
}
/* `.sn-brand-mark.is-wifi` and `.sn-brand-sub` were here — the rail's signal
   glyph and the " Billing" half of the old lockup. Both went; the untagged
   `.sn-brand-mark` above stays because the no-access card still draws the "SN"
   lockup and has no rail to sit in.
   The name itself is back, on the left of the row: quiet weight, not a
   masthead. It is a label telling you which system you are in, and it should
   lose to every row beneath it. */
.sn-brand-name {
  font-size: 14px; font-weight: 600; letter-spacing: .1px;
  color: var(--sn-side-ink); padding-left: 4px;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sn-brand-burger {
  margin-left: auto; background: none; border: 0; color: var(--sn-side-muted); cursor: pointer;
  width: 30px; height: 30px; border-radius: 8px; font-size: 15px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .12s ease, color .12s ease;
}
.sn-brand-burger:hover { background: var(--sn-side-hover); color: var(--sn-side-ink); }
/* Shown ONLY where it's the sole reachable control: a wide viewport with the
   rail expanded. Collapsed to icons on a wide viewport, the top-bar burger
   takes over "bring it back" duty instead (see its own rule) — the collapsed
   rail keeps this element's layout unchanged (.nav-collapsed only tweaks its
   margin below) but it must not be VISIBLE there too, or the icon strip shows
   two. On a narrow viewport the rail starts off-screen, so this button would
   be unreachable until the top-bar one already opened it. Default hidden,
   enabled back on for the one case it's needed. */
/* Visible at EVERY desktop width — expanded and collapsed alike — because it
   is now the only toggle. Hidden below 901px, where the rail itself is
   off-screen and the header's `.sn-burger` takes over. */
.sn-brand-burger { display: none; }
@media (min-width: 901px) {
  .sn-brand-burger { display: inline-flex; }
}
.sn-brand-burger svg { width: 19px; height: 19px; display: block; }

/* Home sits above the categories, sharing the nav's rhythm without being part
   of a fold. */
.sn-home { padding: 2px 8px 6px; }
.sn-home .sn-navitem {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; border-radius: 8px; min-height: 34px;
  color: var(--sn-side-ink); font-size: 13.5px; font-weight: 400;
  text-decoration: none; transition: background .12s ease;
}
.sn-home .sn-navitem:hover { background: var(--sn-side-hover); }
.sn-home .sn-navitem.is-active { background: var(--sn-side-active-bg); color: #fff; font-weight: 500; }
.sn-home .sn-ic { width: 18px; flex: none; opacity: .7; display: inline-flex; align-items: center; justify-content: center; }
.sn-home .sn-navitem.is-active .sn-ic { opacity: 1; }
.sn-home .sn-ic svg { width: 19px; height: 19px; display: block; }
@media (min-width: 901px) {
  .sn-shell.nav-collapsed .sn-home { padding: 2px 9px 6px; }
  .sn-shell.nav-collapsed .sn-home .sn-navitem { justify-content: center; gap: 0; padding: 8px 0; }
}

.sn-nav { padding: 4px 8px 14px; }
/* `.sn-nav h4` was the block heading. The headings are <button class="sn-cat">
   now — the operator asked for every category to fold — and a label that is
   really a control has to be a button. Styled with the dropdowns, further
   down. */
/* Compact, quiet rows. 34px instead of 42, 8px radius, and a hover that is a
   wash rather than a lift — the row should acknowledge the pointer without
   announcing itself. */
.sn-nav a, .sn-nav .sn-navitem {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; margin: 1px 0; border-radius: 8px;
  color: var(--sn-side-ink); font-size: 13.5px; font-weight: 400;
  min-height: 34px; position: relative;
  transition: background .12s ease;
}
.sn-nav a:hover { background: var(--sn-side-hover); color: var(--sn-side-ink); }
.sn-nav .sn-ic { width: 18px; text-align: center; font-size: 14px; flex: none; opacity: .7; }
/* The current page is a flat fill — no gradient, no glow, no shadow. It reads
   as selected because it is lighter than its neighbours, which is the whole
   signal needed, and it does not compete with the actual page content. */
.sn-nav a.is-active {
  background: var(--sn-side-active-bg);
  color: #fff; font-weight: 500;
}
.sn-nav a.is-active .sn-ic { opacity: 1; }
.sn-nav a.is-active:hover { background: #ffffff29; }

/* The signed-in operator, pinned to the foot — a row like any other, not a
   panel. The border that used to divide it is gone: one ground throughout. */
.sn-sideuser {
  margin-top: auto; display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; margin-bottom: 8px; background: none;
  border-radius: 8px; transition: background .12s ease;
}
.sn-nav + .sn-sideuser, .sn-sideuser { margin-left: 8px; margin-right: 8px; }
.sn-sideuser:hover { background: var(--sn-side-hover); }
.sn-sideuser .av {
  width: 28px; height: 28px; border-radius: 50%; flex: none;
  background: #ffffff1f; color: var(--sn-side-ink); display: inline-flex;
  align-items: center; justify-content: center; font-size: 13px;
}
.sn-sideuser .nm { font-size: 13px; font-weight: 500; color: var(--sn-side-ink); display: block; }
.sn-sideuser .rl { font-size: 11.5px; color: var(--sn-side-muted); display: block; }
.sn-sideuser .ca { margin-left: auto; color: var(--sn-side-muted); font-size: 11px; }
/* .is-soon / .sn-soon were here: a greyed row with a "SOON" chip. Both are
   gone with the rail's rewrite — a row that has no page yet is a normal row
   that opens the placeholder, and the placeholder says what it stands in for.
   Greying it in the rail would have said the same thing twice, in the one
   place where the reader cannot read the explanation. */

/* ── main column ───────────────────────────────────────────────────────── */
.sn-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

/* top bar — white, with the page title on the left and a pill search on the
   right. It is a surface now, not a coloured band, so every child takes ink
   from the page palette rather than white-on-dark alphas. */
.sn-top {
  background: var(--sn-header); color: var(--sn-header-ink);
  min-height: 66px; display: flex; align-items: center; gap: 14px;
  padding: 0 22px; position: sticky; top: 0; z-index: 30;
  border-bottom: 1px solid var(--sn-line);
}
/* The rail's toggle, and the reason it is in the TOP bar and not only in the
   rail: when the rail is collapsed to icons the operator needs a control that
   is unmistakably about the menu and always in the same place. It used to be
   mobile-only, which left a collapsed rail on a desktop with no obvious way
   back. */
.sn-burger {
  display: inline-flex; background: none; border: 0; color: var(--sn-ink-soft); cursor: pointer;
  font-size: 20px; width: 40px; height: 40px; border-radius: 9px;
  align-items: center; justify-content: center; flex: none;
}
.sn-burger:hover { background: var(--sn-line-soft); }
/* GONE from the page header on desktop. The rail carries its own toggle at
   every desktop width now — expanded or collapsed to icons — so a second
   button up here was one control too many for one job.
   It survives ONLY below 901px, where the rail is a drawer parked off-screen
   and there is genuinely nothing else to open it with. */
@media (min-width: 901px) {
  .sn-burger { display: none; }
}
/* The breadcrumb is the page's name in the reference: large, bold, dark. The
   trail behind it stays small so the current page still reads as the title. */
.sn-crumb { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.sn-crumb a { font-size: 13.5px; color: var(--sn-muted); }
.sn-crumb a:hover { text-decoration: underline; }
.sn-crumb .sep { opacity: .5; font-size: 13px; color: var(--sn-muted); }
.sn-crumb .cur { font-size: 19px; font-weight: 700; color: var(--sn-ink); }

.sn-topsearch { margin-left: auto; display: flex; align-items: center; }
.sn-topsearch form { display: flex; position: relative; }
.sn-topsearch input {
  height: 42px; width: min(340px, 38vw); padding: 0 42px 0 16px; font-size: 13.5px;
  border: 1px solid var(--sn-line); border-radius: 999px;
  background: #f8fafc; color: var(--sn-ink); outline-offset: -2px;
}
.sn-topsearch input::placeholder { color: var(--sn-muted); }
.sn-topsearch input:focus { background: #fff; border-color: var(--sn-accent); }
/* The magnifier sits inside the pill, so the control reads as one object. The
   glyph is a background SVG rather than a CSS shape: a circle plus a
   box-shadow "handle" never quite lines up, and the stroke colour has to
   follow the theme, which a data: URI can do with currentColor unavailable —
   so the two states are declared explicitly instead. */
.sn-topsearch button {
  position: absolute; right: 4px; top: 4px; width: 34px; height: 34px;
  border: 0; cursor: pointer; border-radius: 50%; font-size: 0;
  background: no-repeat center/17px 17px
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238b98ad' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m16.5 16.5 4 4'/%3E%3C/svg%3E");
}
.sn-topsearch button:hover {
  background-color: var(--sn-line-soft);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23475569' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m16.5 16.5 4 4'/%3E%3C/svg%3E");
}

.sn-user { display: flex; align-items: center; gap: 10px; margin-left: 4px; }
.sn-user-name { font-size: 13.5px; font-weight: 600; color: var(--sn-ink); }
.sn-user-role { font-size: 10.5px; color: var(--sn-muted); text-transform: uppercase; letter-spacing: .06em; }
.sn-avatar {
  width: 38px; height: 38px; border-radius: 50%;
  background: var(--ic-blue-bg); color: var(--ic-blue-ink); display: inline-flex;
  align-items: center; justify-content: center; font-size: 17px;
}
.sn-iconbtn {
  background: none; border: 0; color: var(--sn-ink-soft); cursor: pointer;
  width: 40px; height: 40px; border-radius: 10px; position: relative;
  display: inline-flex; align-items: center; justify-content: center; font-size: 17px;
}
.sn-iconbtn:hover { background: var(--sn-line-soft); }
/* The two top-bar destinations. Anchors, not buttons — they navigate, and a
   thing that navigates should be middle-clickable and copyable like any link. */
.sn-topicon { text-decoration: none; }
.sn-topicon svg { width: 19px; height: 19px; display: block; }

/* The whole TOP-BAR identity block is gone — avatar, username, role and the
   sign-out button with them. All four are accounted for at the foot of the
   rail, which already showed the same name and role on every page; keeping
   both meant the same three facts twice and no room for the shortcuts.
   Hidden rather than deleted because 22 page templates carry this markup and
   shell.js still fills the name in — one CSS rule beats 22 edits, and the
   elements do no harm unseen. Sign-out is re-created inside `.sn-sideuser`,
   so removing this block does not remove the way out.
   `.sn-fullscreen` was injected next to it and is removed for the same reason:
   the browser's own full-screen key does this without spending a slot. */
.sn-user, .sn-fullscreen { display: none; }

/* The rail's sign-out. Sits where the decorative ▾ used to, and only colours
   itself on hover — signing out is not something to invite by accident. */
.sn-sideuser .sn-logout {
  margin-left: auto; flex: none; background: none; border: 0; cursor: pointer;
  color: var(--sn-side-muted); font-size: 14px; line-height: 1;
  width: 26px; height: 26px; border-radius: 7px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .12s ease, color .12s ease;
}
.sn-sideuser .sn-logout:hover { background: #ffffff1f; color: #fff; }
.sn-sideuser .sn-logout:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: -2px; }
/* .sn-badge-n was here — the red count on the bell. The reference draws a "25"
   there; nothing in this service counts unread anything, so no code ever
   emitted the badge and the rule only described a number we would have had to
   invent. It comes back the day something real is counted. */

/* content wrap */
/* margin-inline: auto is load-bearing (2026-09-16), not tidiness: without it
   every page pins to the LEFT edge of the main column and the dead space to
   its right grows without bound as the operator zooms out. See the operator
   screenshot that reported this. */
.sn-content { padding: 22px 22px 48px; max-width: 1400px; width: 100%; margin-inline: auto; }
.sn-pagehead {
  display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap;
  margin-bottom: 18px;
}
.sn-pagehead h1 { margin: 0; font-size: 21px; font-weight: 700; color: #26333f; }
.sn-pagehead .sub { margin: 3px 0 0; color: var(--sn-muted); font-size: 13px; }
.sn-pagehead .spacer { margin-left: auto; }

/* ── buttons ───────────────────────────────────────────────────────────── */
.sn-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 40px; padding: 0 16px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--sn-line); background: #fff; color: var(--sn-ink-soft);
  font-size: 13.5px; font-weight: 600; white-space: nowrap;
}
.sn-btn:hover { background: #f4f7fa; }
.sn-btn.primary {
  background: var(--sn-primary); border-color: var(--sn-primary); color: #fff;
}
.sn-btn.primary:hover { background: var(--sn-primary-dk); }
.sn-btn.danger { border-color: #e6c3c1; color: #a53228; background: #fff; }
.sn-btn.danger:hover { background: #fdf2f1; }
.sn-btn:disabled, .sn-btn[aria-disabled="true"] {
  opacity: .5; cursor: not-allowed; pointer-events: none;
}
.sn-btn.sm { min-height: 32px; padding: 0 11px; font-size: 12.5px; }

/* ── cards ─────────────────────────────────────────────────────────────── */
.sn-card {
  background: var(--sn-card); border-radius: var(--sn-radius);
  box-shadow: var(--sn-shadow); border: 1px solid var(--sn-line-soft);
}
.sn-card + .sn-card { margin-top: 18px; }
.sn-card-h {
  padding: 14px 18px; border-bottom: 1px solid var(--sn-line);
  display: flex; align-items: center; gap: 10px;
}
.sn-card-h h2 { margin: 0; font-size: 15px; font-weight: 700; color: #33404f; }
.sn-card-b { padding: 18px; }

/* ── status-count strip ────────────────────────────────────────────────── */
.sn-strip {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 1px; background: var(--sn-line); border-radius: var(--sn-radius);
  overflow: hidden; border: 1px solid var(--sn-line);
}
.sn-stat {
  background: #fff; padding: 12px 12px 13px; text-align: center;
}
.sn-stat .v {
  font-size: 22px; font-weight: 700; line-height: 1.1;
  color: var(--sn-ink); font-variant-numeric: tabular-nums;
}
.sn-stat .v.is-unknown { color: var(--sn-unknown); }
.sn-stat .k {
  font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase;
  color: var(--sn-muted); margin-top: 4px; font-weight: 600;
}
.sn-stat.is-total { background: #f3fbf8; }
.sn-stat.is-total .v { color: var(--sn-primary-dk); }

/* ── group cards (S2) ──────────────────────────────────────────────────── */
.sn-group { margin-bottom: 16px; }
.sn-group-h {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 13px 16px; cursor: pointer; user-select: none;
}
.sn-group-h:hover { background: #f7f9fc; }
.sn-group-h .caret { transition: transform .15s ease; color: var(--sn-muted); font-size: 12px; }
.sn-group-h[aria-expanded="true"] .caret { transform: rotate(90deg); }
.sn-group-title { font-size: 15px; font-weight: 700; color: #2f3d4b; }
.sn-group-area { font-size: 12.5px; color: var(--sn-muted); }
.sn-group-mini {
  margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap;
  font-size: 12px; color: var(--sn-ink-soft);
}
.sn-group-mini b { font-variant-numeric: tabular-nums; }
.sn-group-body { border-top: 1px solid var(--sn-line); padding: 14px 16px; }
.sn-group-body[hidden] { display: none; }

/* ── DataTables-style table ────────────────────────────────────────────── */
.dt-toolbar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-bottom: 12px;
}
.dt-toolbar .title { font-size: 13.5px; color: var(--sn-muted); font-weight: 600; }
.dt-search { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.dt-search label { font-size: 12.5px; color: var(--sn-muted); }
.dt-search input {
  height: 36px; width: min(240px, 46vw); padding: 0 12px; font-size: 13.5px;
  border: 1px solid var(--sn-line); border-radius: 7px; background: #fff; color: var(--sn-ink);
}
.dt-scroll { overflow-x: auto; border-radius: var(--sn-radius-sm); border: 1px solid var(--sn-line); }
table.dt-table { border-collapse: collapse; width: 100%; min-width: 760px; }
/* A light header with dark ink, not a solid colour bar — the reference keeps
   the accent for the things you can act on, so the table reads as data. */
.dt-table thead th {
  text-align: left; background: #f8fafc; color: var(--sn-ink-soft);
  font-size: 12px; letter-spacing: 0; text-transform: none;
  padding: 12px 13px; white-space: nowrap; font-weight: 700;
  position: sticky; top: 0; border-bottom: 1px solid var(--sn-line);
}
.dt-table th.sortable { cursor: pointer; }
.dt-table th.sortable:hover { background: var(--sn-line-soft); color: var(--sn-ink); }
.dt-table th .sort-ind { opacity: .55; margin-left: 5px; font-size: 10px; }
.dt-table th[aria-sort="ascending"] .sort-ind::after { content: "▲"; opacity: 1; }
.dt-table th[aria-sort="descending"] .sort-ind::after { content: "▼"; opacity: 1; }
.dt-table th[aria-sort="none"] .sort-ind::after,
.dt-table th.sortable:not([aria-sort]) .sort-ind::after { content: "⇅"; }
.dt-table tbody td {
  padding: 10px 13px; border-bottom: 1px solid var(--sn-line-soft);
  font-size: 13px; white-space: nowrap; vertical-align: middle; color: var(--sn-ink);
}
.dt-table tbody tr:hover td { background: #f7f9fc; }
.dt-table tbody tr:last-child td { border-bottom: 0; }
.dt-table td .muted, .muted { color: var(--sn-muted); }
.dt-table td .dash, .dash { color: var(--sn-unknown); }
.dt-table a.link { color: var(--sn-primary-dk); font-weight: 600; }
.dt-table a.link:hover { text-decoration: underline; }
.dt-foot {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 12px; font-size: 12.5px; color: var(--sn-muted);
}
.dt-info { }
.dt-pager { margin-left: auto; display: flex; gap: 6px; }
.dt-pager button {
  min-width: 34px; height: 32px; padding: 0 9px; border: 1px solid var(--sn-line);
  background: #fff; color: var(--sn-ink-soft); border-radius: 6px; cursor: pointer;
  font-size: 12.5px; font-weight: 600;
}
.dt-pager button:hover:not(:disabled) { background: #f2f5f9; }
.dt-pager button:disabled { opacity: .45; cursor: default; }
.dt-pager button.is-current {
  background: var(--sn-primary); border-color: var(--sn-primary); color: #fff;
}

/* "Show [10] entries" — the length control the reference puts above the table. */
.dt-len { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--sn-muted); }
.dt-len select {
  height: 34px; padding: 0 8px; border-radius: 8px; border: 1px solid var(--sn-line);
  background: #fff; color: var(--sn-ink); font-size: 13px; cursor: pointer;
}

/* The online lamp in a row. It carries a text label for screen readers, so the
   colour is a second signal rather than the only one. */
.dt-lamp { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: var(--sn-unknown); }
.dt-lamp.on { background: var(--sn-up); }
.dt-lamp.off { background: #dc2626; }

/* Row actions: small tinted icon buttons, the reference's blue/amber/slate set. */
.dt-acts { display: inline-flex; gap: 5px; }
.dt-act {
  width: 28px; height: 28px; border-radius: 7px; border: 0; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--ic-blue-bg); color: var(--ic-blue-ink); font-size: 13px; line-height: 1;
}
.dt-act:hover { filter: brightness(.94); }
.dt-act.edit { background: var(--ic-amber-bg); color: var(--ic-amber-ink); }
.dt-act.doc  { background: var(--ic-slate-bg); color: var(--ic-slate-ink); }
.dt-act.more { background: transparent; color: var(--sn-muted); }
.dt-act.more:hover { background: var(--sn-line-soft); }

/* ── status + link badges ──────────────────────────────────────────────── */
/* The pill always spells its status out, so the word is the signal and the
   colour only reinforces it. The reference draws no leading dot — the row's
   separate online lamp is the only dot, and two dots per row read as one
   control. */
.badge {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 11px;
  border-radius: 999px; font-size: 11.5px; font-weight: 700; letter-spacing: .01em;
  white-space: nowrap;
}
.badge.st-ok{background:var(--st-ok-bg);color:var(--st-ok-ink);}
.badge.st-free{background:var(--st-free-bg);color:var(--st-free-ink);}
.badge.st-online{background:var(--st-online-bg);color:var(--st-online-ink);}
.badge.st-unverified{background:var(--st-unverified-bg);color:var(--st-unverified-ink);}
.badge.st-grace{background:var(--st-grace-bg);color:var(--st-grace-ink);}
.badge.st-unpaid{background:var(--st-unpaid-bg);color:var(--st-unpaid-ink);}
.badge.st-expired{background:var(--st-expired-bg);color:var(--st-expired-ink);}
.badge.st-expired_unlocked{background:var(--st-expunl-bg);color:var(--st-expunl-ink);}
.badge.st-locked{background:var(--st-locked-bg);color:var(--st-locked-ink);}
.badge.st-no_nid_blocked{background:var(--st-nonid-bg);color:var(--st-nonid-ink);}
.badge.st-disabled{background:var(--st-disabled-bg);color:var(--st-disabled-ink);}

.badge.lk-linked{background:var(--st-ok-bg);color:var(--st-ok-ink);}
.badge.lk-unlinked{background:var(--st-disabled-bg);color:var(--st-disabled-ink);}
.badge.lk-dangling{background:var(--st-expired-bg);color:var(--st-expired-ink);}

/* ── forms ─────────────────────────────────────────────────────────────── */
.sn-form-sec { margin-bottom: 6px; }
.sn-form-sec h3 {
  margin: 0 0 2px; font-size: 14px; font-weight: 700; color: #33404f;
}
.sn-form-sec .hint { margin: 0 0 14px; font-size: 12.5px; color: var(--sn-muted); }
.sn-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 14px 16px;
}
.sn-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.sn-field.col-2 { grid-column: span 2; }
.sn-field label { font-size: 12.5px; font-weight: 600; color: var(--sn-ink-soft); }
.sn-field label .req { color: #c0392b; margin-left: 2px; }
.sn-field input, .sn-field select, .sn-field textarea {
  height: 40px; padding: 0 11px; font-size: 13.5px;
  border: 1px solid var(--sn-line); border-radius: 8px; background: #fff;
  color: var(--sn-ink); width: 100%;
}
.sn-field textarea { height: auto; min-height: 68px; padding: 9px 11px; resize: vertical; }
.sn-field input[readonly], .sn-field input:disabled,
.sn-field select:disabled, .sn-field textarea:disabled {
  background: #f2f4f7; color: var(--sn-ink-soft); cursor: not-allowed;
}
.sn-field .fhint { font-size: 11.5px; color: var(--sn-muted); }

/* A radio row inside a field. `.sn-flabel` is the same weight and size as a
   real <label>, used where the field's caption cannot be a <label for=…>
   because it heads a GROUP of inputs rather than one. */
.sn-flabel { font-size: 12.5px; font-weight: 600; color: var(--sn-ink-soft); }
.sn-radios { display: flex; flex-wrap: wrap; gap: 6px 18px; padding: 5px 0 1px; }
.sn-radios label {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13px; font-weight: 400; color: var(--sn-ink);
  cursor: pointer; white-space: nowrap;
}
.sn-radios input[type="radio"] { accent-color: var(--sn-primary); width: 15px; height: 15px; cursor: pointer; }
.sn-radios input[type="radio"]:disabled { cursor: not-allowed; }
.sn-radios input[type="radio"]:disabled + * { color: var(--sn-muted); }
.sn-field.has-error .sn-radios label { color: var(--st-expired-ink); }
.sn-field .ferror { font-size: 11.5px; color: #c0392b; font-weight: 600; display: none; }
.sn-field.has-error input, .sn-field.has-error select, .sn-field.has-error textarea {
  border-color: #d9534f; background: #fdf3f2;
}
.sn-field.has-error .ferror { display: block; }
.sn-form-actions {
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--sn-line);
}
.sn-form-actions .spacer { margin-left: auto; }

/* MAC repeater */
.sn-macs { display: flex; flex-direction: column; gap: 8px; }
.sn-mac-row { display: flex; gap: 8px; align-items: center; }
.sn-mac-row input { flex: 1; }

/* ── ONU picker ────────────────────────────────────────────────────────── */
.onu-pick { position: relative; }
.onu-results {
  border: 1px solid var(--sn-line); border-radius: 8px; margin-top: 8px;
  max-height: 260px; overflow-y: auto; background: #fff; box-shadow: var(--sn-shadow);
}
.onu-results[hidden] { display: none; }
.onu-item {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 10px 12px; border: 0; border-bottom: 1px solid var(--sn-line-soft);
  background: #fff; cursor: pointer; color: var(--sn-ink);
}
.onu-item:last-child { border-bottom: 0; }
.onu-item:hover, .onu-item:focus-visible { background: #eef7f4; }
.onu-item .s { font-weight: 700; }
.onu-item .m { color: var(--sn-muted); font-size: 12px; }
.onu-picked {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 12px; border: 1px solid #bfe3d8; background: #f0faf6;
  border-radius: 8px; font-size: 13px;
}
.onu-picked .s { font-weight: 700; }

/* ── detail view ───────────────────────────────────────────────────────── */
.sn-cols { display: grid; grid-template-columns: 1.4fr 1fr; gap: 18px; align-items: start; }
.sn-dl { display: grid; grid-template-columns: max-content 1fr; gap: 9px 16px; }
.sn-dl dt { color: var(--sn-muted); font-size: 12.5px; }
.sn-dl dd { margin: 0; font-size: 13.5px; color: var(--sn-ink); word-break: break-word; }
.sn-dl dd.dash { color: var(--sn-unknown); }

.sn-events { list-style: none; margin: 0; padding: 0; }
.sn-event {
  display: flex; gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--sn-line-soft);
}
.sn-event:last-child { border-bottom: 0; }
.sn-event .ev-ic {
  width: 30px; height: 30px; border-radius: 8px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: #eef2f6; font-size: 14px;
}
.sn-event .ev-body { min-width: 0; }
.sn-event .ev-kind { font-weight: 700; font-size: 13px; text-transform: capitalize; }
.sn-event .ev-meta { color: var(--sn-muted); font-size: 12px; }
.sn-event .ev-detail { color: var(--sn-ink-soft); font-size: 12.5px; margin-top: 3px; word-break: break-word; }

.sn-pii-note {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12px;
  color: var(--sn-muted); background: #f2f4f7; border-radius: 6px; padding: 3px 8px;
}

/* ── notes / banners ───────────────────────────────────────────────────── */
.sn-note {
  padding: 11px 14px; border-radius: 8px; font-size: 13px; margin: 0 0 16px;
}
.sn-note[hidden] { display: none; }
/* buttons and their anchor twins: .sn-btn sets display, which out-ranks the
   UA's [hidden] rule - the customer profile's Edit/Change/Raise-work-order
   painted while carrying hidden=true (2026-08-25) */
.sn-btn[hidden] { display: none; }
.sn-note.warn { background: #fff6e5; border: 1px solid #f5dfae; color: #7a5b12; }
.sn-note.err  { background: #fdecea; border: 1px solid #f3c6c2; color: #a1352b; }
.sn-note.info { background: #eaf4f1; border: 1px solid #bfe0d6; color: #16624f; }
/* .ok is distinct from .info: info states a fact, ok is the answer to a
   pass/fail question the reader was waiting on (a connection proved, a
   readiness check that came back clean) — the greener hue says "that
   succeeded" rather than merely "here is what is true". */
.sn-note.ok   { background: var(--st-ok-bg); border: 1px solid #bbe8c9; color: var(--st-ok-ink); }
.sn-note ul { margin: 6px 0 0; padding-left: 18px; }

/* ── states ────────────────────────────────────────────────────────────── */
.sn-empty, .sn-loading {
  padding: 40px 20px; text-align: center; color: var(--sn-muted); font-size: 14px;
}
.sn-spin {
  width: 22px; height: 22px; border-radius: 50%;
  border: 3px solid var(--sn-line); border-top-color: var(--sn-primary);
  display: inline-block; animation: sn-rot .7s linear infinite; vertical-align: -5px; margin-right: 8px;
}
@keyframes sn-rot { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .sn-spin { animation: none; } }

/* ── modal (status change / confirm) ───────────────────────────────────── */
.sn-modal-back {
  position: fixed; inset: 0; background: rgba(16,24,40,.5); z-index: 60;
  display: flex; align-items: center; justify-content: center; padding: 18px;
}
.sn-modal-back[hidden] { display: none; }
.sn-modal {
  background: #fff; border-radius: var(--sn-radius); box-shadow: var(--sn-shadow-lg);
  width: min(460px, 100%); max-height: 90vh; overflow-y: auto;
}
.sn-modal-h { padding: 16px 18px; border-bottom: 1px solid var(--sn-line); display: flex; align-items: center; }
.sn-modal-h h2 { margin: 0; font-size: 16px; font-weight: 700; }
.sn-modal-b { padding: 18px; display: flex; flex-direction: column; gap: 12px; }
.sn-modal-f { padding: 14px 18px; border-top: 1px solid var(--sn-line); display: flex; gap: 10px; justify-content: flex-end; }

/* ── toast ─────────────────────────────────────────────────────────────── */
.sn-toasts { position: fixed; right: 18px; bottom: 18px; z-index: 80; display: flex; flex-direction: column; gap: 10px; }
.sn-toast {
  background: #10201b; color: #eaf5f1; padding: 12px 16px; border-radius: 9px;
  box-shadow: var(--sn-shadow-lg); font-size: 13.5px; max-width: 340px;
  border-left: 4px solid var(--sn-accent);
}
.sn-toast.err { border-left-color: #e0554b; }

/* ── the rail, collapsed to icons ────────────────────────────────────────── */
/* Closing the menu on a wide screen narrows it to a 74px strip rather than
   removing it: every row keeps its icon and its `title`, so the whole menu is
   still one click (and one hover) away, and the page gets ~190px back. Scoped
   to the desktop breakpoint on purpose — below it the rail is already a drawer
   over the page, and the two states would fight. */
@media (min-width: 901px) {
  .sn-side { transition: width .18s ease; }
  .sn-shell.nav-collapsed { --sn-side-w: 74px; }
  /* Everything that is words rather than symbols. */
  .sn-shell.nav-collapsed .sn-brand-name,
  .sn-shell.nav-collapsed .sn-navlabel,
  .sn-shell.nav-collapsed .sn-fold,
  .sn-shell.nav-collapsed .sn-sub,
  .sn-shell.nav-collapsed .sn-sideuser .tx,
  /* Sign-out goes with the name it belongs to: a 74px strip has no room for a
     second control, and expanding the rail to reach it is one click. */
  .sn-shell.nav-collapsed .sn-sideuser .sn-logout { display: none; }
  /* Centre the one control the strip has at its top — the way back out of it. */
  .sn-shell.nav-collapsed .sn-brand { justify-content: center; padding: 6px 0 2px; }
  .sn-shell.nav-collapsed .sn-brand-burger { margin-left: 0; }
  .sn-shell.nav-collapsed .sn-nav { padding: 6px 9px 14px; }
  .sn-shell.nav-collapsed .sn-nav a {
    justify-content: center; gap: 0; padding: 8px 0;
  }
  .sn-shell.nav-collapsed .sn-sideuser {
    justify-content: center; margin-left: 8px; margin-right: 8px; padding: 10px 0;
  }
  /* A fold that is open when the rail closes must not leave a gap behind its
     hidden children. */
  .sn-shell.nav-collapsed .sn-block + .sn-block { margin-top: 10px; }
  .sn-shell.nav-collapsed .sn-sideuser { justify-content: center; padding: 14px 8px; }
}

/* ── scrim for mobile drawer ───────────────────────────────────────────── */
.sn-scrim { position: fixed; inset: 0; background: rgba(0,0,0,.4); z-index: 25; }
.sn-scrim[hidden] { display: none; }

/* ── responsive ────────────────────────────────────────────────────────── */
@media (max-width: 1040px) {
  .sn-cols { grid-template-columns: 1fr; }
}
@media (max-width: 900px) {
  .sn-side {
    position: fixed; left: 0; top: 0; z-index: 40; height: 100vh;
    transform: translateX(-100%); transition: transform .2s ease;
    box-shadow: var(--sn-shadow-lg);
  }
  .sn-shell.nav-open .sn-side { transform: translateX(0); }
  .sn-content { padding: 16px 14px 40px; }
  .sn-field.col-2 { grid-column: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .sn-side { transition: none; }
}
@media (max-width: 560px) {
  .sn-topsearch { display: none; }
  .sn-user-name, .sn-user-role { display: none; }
}

/* ── rail typography ─────────────────────────────────────────────────────── */
.sn-navlabel { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── category dropdowns ──────────────────────────────────────────────────────
   MAIN / SUPPORT / NETWORK / SYSTEM are controls now, not labels: each folds
   its own rows. They keep the reference's small-caps look so the rail still
   reads as a labelled list, and each fold is independent — closing one must
   not close the others, because four categories ARE the shape of this menu. */
/* Quiet section labels: sentence-weight, no wide tracking, no uppercase
   shouting. They are there to be found when looked for and to disappear when
   not — the rows underneath are what the eye is scanning. */
.sn-cat {
  display: flex; align-items: center; width: 100%;
  background: none; border: 0; cursor: pointer; text-align: left;
  font: inherit; font-size: 11.5px; letter-spacing: .02em; font-weight: 500;
  text-transform: none; color: var(--sn-side-muted);
  padding: 6px 10px; margin: 14px 0 1px; border-radius: 8px;
  transition: color .12s ease, background .12s ease;
}
.sn-cat:hover { color: var(--sn-side-ink); background: var(--sn-side-hover); }
.sn-cat:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: -2px; }
.sn-cat-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sn-cat-caret { flex: none; font-size: 9px; opacity: .5; transition: transform .16s ease; }
/* Shut points right, open points down — the caret follows the fold rather
   than being decoration that has to be remembered. */
.sn-block:not(.open) .sn-cat-caret { transform: rotate(-90deg); }
.sn-catbody[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) {
  .sn-cat-caret { transition: none; }
}
/* A collapsed rail has no room for a category header, and its rows are already
   reduced to icons — a fold control there would hide the whole menu behind a
   strip of chevrons. */
@media (min-width: 901px) {
  .sn-shell.nav-collapsed .sn-cat { display: none; }
  .sn-shell.nav-collapsed .sn-catbody[hidden] { display: block; }
}

/* ── dashboard layout helpers ────────────────────────────────────────────── */
.sn-cardgrid { display: grid; gap: 18px; }
@media (min-width: 900px) { .sn-cardgrid.two { grid-template-columns: 1fr 1fr; } }
@media (min-width: 900px)  { .sn-cardgrid.three { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1400px) { .sn-cardgrid.three { grid-template-columns: 1fr 1fr 1fr; } }
.sn-stat .k.plant { text-transform: none; letter-spacing: 0; }

.sn-hint { font-size: 12px; color: var(--sn-ink-soft); margin: 0; }
/* An em dash quoted inside a sentence is being *named*, not standing in for a
   figure, so it takes the prose ink. The muted --sn-unknown grey is right for a
   dash sitting in a value slot, but at 1.7:1 it is unreadable mid-sentence. */
.sn-note .dash, .sn-hint .dash { color: inherit; font-weight: 700; }
/* Links carry an underline as well as the house green — colour is never the
   only signal that something is a link. */
a.sn-link, .sn-hint a { color: var(--sn-primary-dk); font-weight: 600; text-decoration: underline; }

/* ── dashboard overview rows (the operator-panel card grid) ──────────────── */
/* Four cards across on a wide screen, two on a tablet, stacked on a phone.
   560px and 900px already exist in this sheet; 1240px is new, because between
   900px (where the rail turns into a drawer) and ~1240px the 262px rail leaves
   too little width for four cards to hold a large figure and a full label. */
.sn-row { display: grid; gap: 16px; grid-template-columns: 1fr; margin: 0 0 16px; }
@media (min-width: 560px)  { .sn-row { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1240px) { .sn-row { grid-template-columns: repeat(4, 1fr); } }
/* the chart row: one panel per line until three fit side by side */
.sn-row.three { grid-template-columns: 1fr; }
@media (min-width: 1240px) { .sn-row.three { grid-template-columns: repeat(3, 1fr); } }
/* the reference's KPI bands are five and six across. They step down through
   three and two rather than jumping straight to one, because a 27px figure
   with a full label needs ~210px and anything narrower truncates. */
.sn-row.five, .sn-row.six { grid-template-columns: 1fr; }
@media (min-width: 560px)  { .sn-row.five, .sn-row.six { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px)  { .sn-row.five, .sn-row.six { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1400px) { .sn-row.five { grid-template-columns: repeat(5, 1fr); } }
@media (min-width: 1400px) { .sn-row.six  { grid-template-columns: repeat(6, 1fr); } }
/* charts band: two wide line panels, then two narrower donut panels */
.sn-row.charts { grid-template-columns: 1fr; }
@media (min-width: 900px)  { .sn-row.charts { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1500px) { .sn-row.charts { grid-template-columns: 1.15fr 1.15fr 1fr 1fr; } }
/* the table + right-hand column. align-items:start stops the shorter column
   from being stretched to the taller one's height and trailing dead white. */
.sn-row.split { grid-template-columns: 1fr; align-items: start; }
@media (min-width: 1240px) { .sn-row.split { grid-template-columns: minmax(0,1fr) 340px; } }
/* A split whose second column is empty is not a split. The routers page keeps
   its add-form shut until asked for, and without this the list would sit
   beside a 340px hole the whole time.
   Scoped to #rt-top by id, NOT to `.sn-row.split` — the dashboard's recent-users
   band is the same class and would collapse to one column with it. */
@media (min-width: 1240px) {
  #rt-top:not(.has-form) { grid-template-columns: minmax(0,1fr); }
}
/* two equal panels — the router's throughput and session graphs */
.sn-row.two { grid-template-columns: 1fr; }
@media (min-width: 1100px) { .sn-row.two { grid-template-columns: 1fr 1fr; } }

/* ── the router screen ───────────────────────────────────────────────────── */
/* These are the shapes the Routers page is built from: a sub-heading inside a
   card, a run of chips for profiles and pools, a key/value block for what the
   box said about itself, a plain table, and the two small pieces that carry the
   answers the operator asks for by name — what this RouterOS login may do, and
   how many subscribers are up right now. */
.sn-sub-h {
  margin: 22px 0 10px; font-size: 13px; font-weight: 700; color: #33404f;
  letter-spacing: .01em;
}
.sn-sub-h:first-child { margin-top: 0; }

.sn-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.sn-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px; border-radius: 999px; font-size: 12.5px;
  background: var(--sn-line-soft); border: 1px solid var(--sn-line);
  color: var(--sn-ink-soft); white-space: nowrap;
}
.sn-chip b { color: var(--sn-ink); font-variant-numeric: tabular-nums; }

.sn-kvs {
  display: grid; gap: 1px; background: var(--sn-line);
  border: 1px solid var(--sn-line); border-radius: var(--sn-radius-sm);
  overflow: hidden; grid-template-columns: 1fr;
}
@media (min-width: 700px)  { .sn-kvs { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .sn-kvs { grid-template-columns: repeat(4, 1fr); } }
.sn-kv {
  background: #fff; padding: 11px 14px; display: flex; flex-direction: column; gap: 3px;
}
.sn-kv span { font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase; color: var(--sn-muted); font-weight: 600; }
.sn-kv b { font-size: 14px; color: var(--sn-ink); overflow-wrap: anywhere; }

.sn-tablewrap { overflow-x: auto; }
.sn-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.sn-table th {
  text-align: left; padding: 10px 12px; font-size: 11px; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase; color: var(--sn-muted);
  background: var(--sn-line-soft); border-bottom: 1px solid var(--sn-line);
  white-space: nowrap;
}
.sn-table td { padding: 11px 12px; border-bottom: 1px solid var(--sn-line-soft); vertical-align: top; }
.sn-table tr:last-child td { border-bottom: 0; }
.sn-table .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.sn-table th.num { text-align: right; }
.sn-table .sub { font-size: 12px; color: var(--sn-muted); margin-top: 2px; }
.sn-table .acts { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; }

.sn-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-top: 16px; }
.sn-warn { color: #b45309; font-weight: 600; }

/* What the saved RouterOS login may do, as the router itself answered. Three
   states and three colours, because "the router would not say" is a real
   answer and must not be drawn as a refusal. */
.sn-caps { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.sn-cap {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 600;
  border: 1px solid transparent; white-space: nowrap; cursor: help;
}
.sn-cap.ok { background: var(--st-ok-bg); color: var(--st-ok-ink); }
.sn-cap.no { background: var(--st-expired-bg); color: var(--st-expired-ink); }
.sn-cap.unknown { background: var(--sn-line-soft); color: var(--sn-muted); border-color: var(--sn-line); }
.sn-cap.grp { background: var(--ic-blue-bg); color: var(--ic-blue-ink); cursor: default; }

/* The one figure on the list that changes by itself. The dot is decoration —
   the number and its tooltip carry the meaning. */
.sn-live {
  display: inline-flex; align-items: center; gap: 6px;
  font-weight: 700; color: var(--sn-ink); font-variant-numeric: tabular-nums;
}
.sn-live .dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--sn-up); flex: none;
}

/* ── quick actions: the coloured pill row under the charts ───────────────── */
.sn-quick { display: flex; flex-wrap: wrap; gap: 10px; margin: 0 0 16px; }
.sn-qbtn {
  display: inline-flex; align-items: center; gap: 8px; min-height: 42px;
  padding: 0 17px; border-radius: 10px; border: 0; cursor: pointer;
  background: var(--q-bg, var(--sn-primary)); color: #fff;
  font-size: 13.5px; font-weight: 600; white-space: nowrap;
  box-shadow: 0 2px 8px rgba(16,24,40,.10);
}
.sn-qbtn:hover { filter: brightness(1.07); }
.sn-qbtn .qi { font-size: 15px; line-height: 1; }
.sn-qbtn.q-indigo { --q-bg:#6366f1; }
.sn-qbtn.q-green  { --q-bg:#16a34a; }
.sn-qbtn.q-sky    { --q-bg:#0ea5e9; }
.sn-qbtn.q-amber  { --q-bg:#f97316; }
.sn-qbtn.q-teal   { --q-bg:#0d9488; }
.sn-qbtn.q-violet { --q-bg:#8b5cf6; }
.sn-qbtn.q-blue   { --q-bg:#2563eb; }
.sn-qbtn.q-cyan   { --q-bg:#0891b2; }
.sn-qbtn.q-emerald { --q-bg:#059669; }

/* ── side list cards (Top Routers, Recent Tickets) ───────────────────────── */
.sn-list-card { display: flex; flex-direction: column; }
.sn-list-card .sn-card-h .more {
  margin-left: auto; font-size: 12.5px; font-weight: 600; color: var(--sn-primary);
}
.sn-list-card .sn-card-h .more:hover { text-decoration: underline; }
.sn-minitable { width: 100%; border-collapse: collapse; }
.sn-minitable th {
  text-align: left; font-size: 11px; font-weight: 700; color: var(--sn-muted);
  text-transform: none; padding: 0 0 9px; border-bottom: 1px solid var(--sn-line);
}
.sn-minitable td {
  padding: 11px 0; font-size: 13px; border-bottom: 1px solid var(--sn-line-soft);
  color: var(--sn-ink); vertical-align: middle;
}
.sn-minitable tr:last-child td { border-bottom: 0; }
.sn-minitable td.num { text-align: right; font-variant-numeric: tabular-nums; }
.sn-minitable td.st { text-align: right; font-weight: 600; }
.sn-minitable td.st.on { color: var(--sn-up); }
.sn-minitable td.st.off { color: #dc2626; }

/* One ticket in the side list: a coloured spine, the reference, and its state. */
.sn-ticketrow {
  display: flex; align-items: flex-start; gap: 11px; padding: 11px 0 11px 12px;
  border-left: 3px solid var(--tk, var(--sn-primary));
  border-bottom: 1px solid var(--sn-line-soft);
}
.sn-ticketrow:last-child { border-bottom: 0; }
.sn-ticketrow.tk-open { --tk:#f97316; }
.sn-ticketrow.tk-progress { --tk:#2563eb; }
.sn-ticketrow.tk-resolved { --tk:#16a34a; }
.sn-ticketrow .ref { font-size: 12.5px; font-weight: 700; color: var(--sn-ink); display: block; }
.sn-ticketrow .sub { font-size: 12px; color: var(--sn-muted); display: block; margin-top: 2px; }
.sn-ticketrow .pill {
  margin-left: auto; flex: none; align-self: center;
  padding: 3px 10px; border-radius: 999px; font-size: 11px; font-weight: 700;
}
.tk-open .pill { background: var(--ic-amber-bg); color: var(--ic-amber-ink); }
.tk-progress .pill { background: var(--ic-blue-bg); color: var(--ic-blue-ink); }
.tk-resolved .pill { background: var(--ic-green-bg); color: var(--ic-green-ink); }

/* ── simple tab switcher (router connectivity vs. its packages) ──────────── */
.sn-tabs { display: flex; gap: 4px; margin: 0 0 16px; border-bottom: 1px solid var(--sn-line-soft); }
.sn-tab {
  padding: 9px 14px; border: 0; background: none; cursor: pointer;
  font-size: 13.5px; font-weight: 600; color: var(--sn-muted);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.sn-tab:hover { color: var(--sn-ink-soft); }
.sn-tab.active { color: var(--sn-accent); border-bottom-color: var(--sn-accent); }

/* ── the small stat strip along the foot of the dashboard ────────────────── */
.sn-ministat {
  background: var(--sn-card); border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius); box-shadow: var(--sn-shadow);
  padding: 15px 17px; display: flex; align-items: center; gap: 12px;
}
.sn-ministat .b { flex: 1 1 auto; min-width: 0; }
.sn-ministat .k { font-size: 12.5px; color: var(--sn-ink-soft); font-weight: 600; }
.sn-ministat .v {
  font-size: 21px; font-weight: 800; color: var(--sn-ink); margin-top: 4px;
  font-variant-numeric: tabular-nums; letter-spacing: -.3px;
}
.sn-ministat .v.dash { color: var(--sn-muted); }

/* ── KPI cards (label, figure, trend — pastel icon disc on the right) ────── */
.sn-kpi {
  background: var(--sn-card); border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius); box-shadow: var(--sn-shadow);
  padding: 17px 18px; display: flex; align-items: flex-start; gap: 12px;
}
/* A column, so the reason line can be pushed to the foot of the card. Without
   it a two-line label on one card and a one-line label on the next put their
   figures at different heights and the band stops scanning as a row. */
.sn-kpi-b { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; height: 100%; }
/* Label above the figure, the way the reference card reads. Two lines are
   reserved whether or not the label needs them, so a card whose name wraps
   ("Total Sales (This Month)") keeps its figure on the same baseline as the
   card beside it — otherwise the band's big numbers sit at two heights. */
.sn-kpi-k {
  margin: 0 0 7px; font-size: 12.5px; font-weight: 600; letter-spacing: 0;
  text-transform: none; color: var(--sn-ink-soft);
  min-height: 2.6em; display: flex; align-items: flex-start;
}
.sn-kpi-fig {
  font-size: 27px; font-weight: 800; line-height: 1.1; color: var(--sn-ink);
  font-variant-numeric: tabular-nums; overflow-wrap: anywhere; letter-spacing: -.4px;
}
/* An unmeasured figure is large text, so --sn-muted (3:1 on white) clears the
   large-text bar; the reason note beneath carries the meaning in words. It is
   set lighter than a real figure so an em dash at 800 weight does not read as
   a deliberate strike-through. */
.sn-kpi-fig.dash { color: var(--sn-muted); font-weight: 600; }
/* The reason line sits where the reference puts its trend line: at the foot of
   the card, clamped to two lines so one long explanation cannot make its card
   taller than the rest of the band. The full text stays in the title. */
.sn-kpi-note {
  margin: 9px 0 0; padding-top: 2px; font-size: 11.5px; line-height: 1.4;
  color: var(--sn-ink-soft); margin-top: auto;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.sn-kpi-note:empty { display: none; }

/* .sn-kpi-trend was here — the "↑ 12.5% from last month" line under a KPI, in
   its up / down / live / off forms. Nothing renders it: every figure that would
   carry a trend needs a previous period to compare against, and the payments
   and session feeds that would supply one are not built. The card shows
   .sn-kpi-note instead, which names what the figure is waiting for. Deleted
   rather than kept warm — style for markup nobody emits is read as a feature
   that exists, and the next person spends an afternoon looking for it. */

.sn-kpi-ic {
  width: 48px; height: 48px; border-radius: 50%; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--ic-blue-bg); color: var(--ic-blue-ink);
}
.sn-kpi-ic svg { width: 23px; height: 23px; display: block; }
.sn-kpi-ic.violet { background: var(--ic-violet-bg); color: var(--ic-violet-ink); }
.sn-kpi-ic.green  { background: var(--ic-green-bg);  color: var(--ic-green-ink); }
.sn-kpi-ic.amber  { background: var(--ic-amber-bg);  color: var(--ic-amber-ink); }
.sn-kpi-ic.rose   { background: var(--ic-rose-bg);   color: var(--ic-rose-ink); }
.sn-kpi-ic.blue   { background: var(--ic-blue-bg);   color: var(--ic-blue-ink); }
.sn-kpi-ic.sky    { background: var(--ic-sky-bg);    color: var(--ic-sky-ink); }
.sn-kpi-ic.teal   { background: var(--ic-teal-bg);   color: var(--ic-teal-ink); }
.sn-kpi-ic.slate  { background: var(--ic-slate-bg);  color: var(--ic-slate-ink); }

/* The reference highlights one card per row by tinting its label blue rather
   than by inverting the whole card — a louder card would out-shout its row. */
.sn-kpi.is-feature .sn-kpi-k { color: var(--sn-primary); font-weight: 700; }

/* progress meter. With no reading at all the track is hatched rather than left
   empty — an empty bar reads as "0%", which is exactly the lie we avoid. */
.sn-meter { height: 9px; border-radius: 999px; background: var(--sn-line); overflow: hidden; margin-top: 11px; }
.sn-meter-fill { display: block; height: 100%; background: var(--sn-primary); border-radius: 999px; }
.sn-meter.is-unknown {
  background-image: repeating-linear-gradient(135deg,
    var(--sn-line) 0 5px, var(--sn-line-soft) 5px 10px);
}

/* The coloured-tile dashboard was here — .t-green / .t-blue / .t-navy /
   .t-maroon / .t-amber feeding --tile-bg, and the .sn-tile / -b / -row / -note
   / -f block that painted rows 2 and 3 as saturated cards with a darker footer
   link. It was the design BEFORE this one: the operator's reference builds the
   same figures as white cards with a pastel icon disc, which is .sn-kpi, and
   every page moved to that. Not one file emitted a tile any more, so all of it
   is gone rather than left as a second dashboard nobody can reach. */

/* ── row 4: chart panels (centred title, options button on the right) ───── */
.sn-panel {
  display: flex; flex-direction: column;
  background: var(--sn-card); border: 1px solid var(--sn-line-soft);
  border-radius: var(--sn-radius); box-shadow: var(--sn-shadow);
}
/* Title on the left, its range control on the right — no centre column and no
   bottom rule, the way the reference panels are drawn. */
.sn-panel-h {
  display: flex; align-items: center; gap: 10px;
  padding: 15px 17px 4px;
}
.sn-panel-h h2 {
  margin: 0; text-align: left; flex: 1 1 auto; min-width: 0;
  font-size: 14.5px; font-weight: 700; color: var(--sn-ink);
}
.sn-panel-menu {
  width: 30px; height: 30px; border: 0; border-radius: 8px;
  background: none; color: var(--sn-muted); cursor: pointer;
  font-size: 16px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}
.sn-panel-menu:hover { background: var(--sn-line-soft); color: var(--sn-ink-soft); }
/* The range picker. It is a real <select> so it is keyboard- and
   screen-reader-operable; the reference's chevron is the native one. */
.sn-range {
  height: 32px; padding: 0 9px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--sn-line); background: #fff; color: var(--sn-ink-soft);
  font-size: 12.5px; font-weight: 600;
}
.sn-range:hover { background: var(--sn-line-soft); }
.sn-panel-b { flex: 1 1 auto; padding: 8px 14px 16px; }

/* ── inline SVG charts (no library, house palette, theme colours) ────────── */
.ct-svg { width: 100%; height: auto; display: block; font-family: inherit; overflow: visible; }
.ct-svg text { font-family: inherit; }
.ct-lbl { fill: var(--sn-ink-soft); font-size: 12px; }
.ct-val { fill: var(--sn-ink); font-size: 12px; font-weight: 700; }
.ct-track { fill: var(--sn-line-soft); }
.ct-grid { stroke: var(--sn-line); stroke-width: 1; }
.ct-ax { fill: var(--sn-muted); font-size: 10.5px; }
.ct-line { stroke: var(--sn-primary); stroke-width: 2.5; fill: none; stroke-linejoin: round; stroke-linecap: round; }
.ct-dot { fill: var(--sn-primary-dk); }

/* frame parts shared by the panel-sized primitives (lineMulti / gaugeHalf /
   barV): the axes, the gauge track, the in-frame "why this is empty" note and
   the gauge's centre readout. */
.ct-axis { stroke: var(--sn-line); stroke-width: 1; }
.ct-track-arc { fill: var(--sn-line-soft); }
.ct-note { fill: var(--sn-muted); font-size: 11px; }
.ct-center-v { fill: var(--sn-ink); font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; }
.ct-center-v.is-unknown { fill: var(--sn-unknown); }
.ct-center-k { fill: var(--sn-muted); font-size: 10.5px; }

/* HTML legend (not SVG text) so it wraps on narrow screens, stays selectable
   and reads as a list to a screen reader. The series name is always spelled
   out, so colour is never the only signal. */
.ct-legend {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px;
  list-style: none; margin: 10px 0 0; padding: 0;
}
.ct-legend li { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--sn-ink-soft); }
.ct-legend .sw { width: 10px; height: 10px; border-radius: 3px; flex: none; }

/* ── honest empty-state panel (unavailable / being-set-up) ───────────────── */
.sn-emptybox { text-align: center; padding: 40px 22px; }
.sn-emptybox .ic {
  width: 58px; height: 58px; border-radius: 14px; margin: 0 auto 14px;
  display: inline-flex; align-items: center; justify-content: center; font-size: 26px;
  background: #eef4f2; color: var(--sn-primary-dk);
}
.sn-emptybox h3 { margin: 0 0 6px; font-size: 16px; color: #33404f; }
.sn-emptybox p { margin: 0 auto; max-width: 540px; color: var(--sn-muted); font-size: 13.5px; }
.sn-emptybox p + p { margin-top: 8px; }
.sn-emptybox .sn-btn { margin-top: 18px; }

@media (prefers-reduced-motion: reduce) {
  .sn-nav a .sn-dot::before { transition: none; }
}

/* ── ticket screens ──────────────────────────────────────────────────────── */
/* The maXim reference: a green ➕ up by the breadcrumb title, a row of small
   labelled filter controls, teal table headers (dt-table already carries the
   house teal). Everything else reuses the module's existing primitives. */
.sn-plusbtn {
  width: 42px; height: 42px; border-radius: 10px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: #2e7d32; color: #fff; font-size: 22px; font-weight: 700;
  line-height: 1; box-shadow: var(--sn-shadow); border: 0; cursor: pointer;
}
.sn-plusbtn:hover { background: #1f5f24; }

/* The filter row: labelled controls sitting side by side, wrapping on narrow
   screens; the buttons sit on the controls' baseline. */
.sn-filterrow {
  display: flex; flex-wrap: wrap; gap: 12px 14px; align-items: flex-end;
}
.sn-filterrow .sn-field { flex: 0 1 auto; width: auto; min-width: 168px; }
.sn-filterrow .sn-field.dates { min-width: 150px; }
.sn-filterrow .actions { display: flex; gap: 10px; }
@media (max-width: 560px) {
  .sn-filterrow .sn-field { flex: 1 1 100%; }
  .sn-filterrow .actions { flex: 1 1 100%; }
}

/* Status pill: the word always spelled out; the meta's colour map arrives as
   --tk-c (dot + border), the text stays page ink so contrast never depends on
   the feed's palette. */
.tk-stpill {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px;
  border-radius: 999px; font-size: 11.5px; font-weight: 700; white-space: nowrap;
  background: #fff; border: 1.5px solid var(--tk-c, var(--sn-muted));
  color: var(--sn-ink);
}
.tk-stpill::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: var(--tk-c, var(--sn-muted)); flex: none;
}

/* The ticket drawer reuses the house modal, wider, and its close button needs
   a hover that shows on white. */
.sn-modal.lg { width: min(760px, 100%); }
.sn-modal-h .spacer { margin-left: auto; }
.sn-modal-h .sn-iconbtn { color: var(--sn-ink-soft); }
.sn-modal-h .sn-iconbtn:hover { background: #f2f5f9; }
.tk-idbtn {
  background: none; border: 0; padding: 0; cursor: pointer; font: inherit;
  color: var(--sn-primary-dk); font-weight: 600;
}
.tk-idbtn:hover { text-decoration: underline; }

/* ── SMS screens ─────────────────────────────────────────────────────────── */
/* The SMS pages reuse the module's cards, grid, notes and table wholesale.
   These are the few primitives they add: a checkbox row (the house
   `.sn-field input` rule would stretch a checkbox to 40px tall), a field that
   spans the whole grid for URL templates and message bodies, the placeholder
   chips, and the block that shows a provider's reply verbatim. */
.sn-field.col-full { grid-column: 1 / -1; }

.sn-check { display: inline-flex; align-items: center; gap: 9px; min-height: 26px; }
.sn-check input[type="checkbox"], .sn-check input[type="radio"] {
  width: 18px; height: 18px; min-height: 0; padding: 0; margin: 0; flex: none;
  accent-color: var(--sn-primary);
}
.sn-check label { font-size: 13px; font-weight: 600; color: var(--sn-ink-soft); }

/* A radio group is a real <fieldset>; the legend is its label. */
.sms-modes { border: 0; margin: 0 0 14px; padding: 0; display: flex; gap: 18px; flex-wrap: wrap; }
.sms-modes legend {
  padding: 0; margin-bottom: 8px; font-size: 12.5px; font-weight: 600; color: var(--sn-ink-soft);
}

.sms-mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 12px;
}
.sms-token {
  display: inline-block; background: #eef4f2; color: #0a5c4c; border: 1px solid #cfe4dd;
  border-radius: 5px; padding: 1px 6px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 11.5px;
}
button.sms-token { cursor: pointer; }
button.sms-token:hover { background: #dcece7; }
.sms-tokens { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 6px 0 0; }
.sms-example { margin: 7px 0 0; font-size: 11.5px; color: var(--sn-muted); overflow-wrap: anywhere; }

/* The provider's reply, verbatim: the operator is debugging a gateway, so the
   raw body is the point. Dark block = "this is the wire, not our words". */
.sms-pre {
  margin: 8px 0 0; padding: 11px 13px; border-radius: 8px;
  background: var(--sn-side); color: var(--sn-side-ink);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 12px; line-height: 1.5;
  white-space: pre-wrap; word-break: break-word;
  max-height: 240px; overflow: auto;
}
.sms-result .sn-dl { margin-top: 8px; }
.sms-result p { margin: 10px 0 0; }

/* Character / segment counter under a message box. */
.sms-counter { margin: 6px 0 0; font-size: 12px; color: var(--sn-ink-soft); font-variant-numeric: tabular-nums; }
.sms-counter.is-multi { color: #8a5a10; font-weight: 600; }

/* ── the rail, as the reference draws it ─────────────────────────────────── */
/* Flat rows under small uppercase block headings — MAIN / SUPPORT / NETWORK /
   SYSTEM — with the current row a solid blue pill. A row that owns more screens
   than the reference names carries a chevron and folds them out beneath it;
   the fold's state is carried by aria-expanded, so the chevron is decoration
   and never the only signal. */
.sn-block + .sn-block { margin-top: 2px; }
.sn-nav .sn-navitem { text-decoration: none; }
/* The icon is a 24-box line glyph, stroked with currentColor so it follows the
   row through rest, hover and the active pill without a second rule. */
.sn-nav .sn-ic svg { width: 19px; height: 19px; display: block; }
.sn-nav .sn-ic { display: inline-flex; align-items: center; justify-content: center; }

/* The chevron. A real button inside the row: the row navigates, the chevron
   only folds — so a parent with a page of its own is not demoted to a folder. */
.sn-fold {
  margin-left: auto; flex: none; background: none; border: 0; cursor: pointer;
  color: inherit; opacity: .55; font-size: 15px; line-height: 1;
  width: 24px; height: 24px; border-radius: 6px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: transform .15s ease;
}
.sn-fold:hover { opacity: 1; background: #ffffff1f; }
.sn-fold[aria-expanded="true"] { transform: rotate(90deg); }
.sn-fold:focus-visible { outline: 2px solid var(--sn-accent); outline-offset: -2px; }

/* A row whose child is the current page: brought up to full ink, but NOT
   given the fill — the fill belongs to the page you are actually on, and two
   filled rows in one rail is two answers to "where am I". */
.sn-nav .sn-navitem.is-within { color: #fff; background: none; }

/* The fold itself: children sit indented on a hairline, smaller and quieter
   than their parent, so the rail still reads as one flat list of names. */
.sn-sub { margin: 1px 0 4px 22px; padding-left: 10px; border-left: 1px solid #ffffff14; }
.sn-sub[hidden] { display: none; }
.sn-sub a {
  display: flex; align-items: center; gap: 9px;
  padding: 6px 10px; margin: 1px 0; border-radius: 8px;
  color: var(--sn-side-muted); font-size: 12.5px; min-height: 30px;
}
.sn-sub a:hover { background: var(--sn-side-hover); color: var(--sn-side-ink); }
.sn-sub a.is-active { color: #fff; font-weight: 500; background: var(--sn-side-active-bg); }
.sn-sub .sn-dot {
  width: 5px; height: 5px; border-radius: 50%; flex: none;
  background: currentColor; opacity: .6;
}
.sn-sub a.is-active .sn-dot { opacity: 1; background: var(--sn-accent); }

@media (prefers-reduced-motion: reduce) {
  .sn-fold { transition: none; }
}

/* ── refused: this account is not scoped to billing ──────────────────────── */
/* CONTROL-PLANE.md §2.3. The shared cookie is valid on every hostname behind
   the gateway, so a map-only account lands on a real billing page holding a
   real session and the server answers 403. shell.js replaces the whole body
   with this card rather than framing it in the sidebar — a billing menu is a
   list of things this account may not have, and it should not be the
   consolation prize for being refused. There is no styling for a "partial"
   state because there is no partial state: you are in billing or you are not. */
.sn-noaccess {
  display: flex; align-items: center; justify-content: center;
  min-height: 100vh; padding: 24px; background: var(--sn-page);
}
.sn-noaccess-card {
  max-width: 460px; width: 100%; text-align: center;
  background: var(--sn-card); border: 1px solid var(--sn-line-soft);
  border-radius: var(--sn-radius); box-shadow: var(--sn-shadow);
  padding: 34px 30px;
}
/* display:flex, not the base inline-flex: `margin: 0 auto` only centres a
   block-level box, and the mark is the only thing above the headline. */
.sn-noaccess-card .sn-brand-mark { display: flex; margin: 0 auto 14px; }
.sn-noaccess-card h1 { margin: 0 0 10px; font-size: 19px; color: var(--sn-ink); }
.sn-noaccess-card p { margin: 0; color: var(--sn-ink-soft); line-height: 1.55; }
.sn-noaccess-act { margin-top: 20px !important; }

/* .sn-ext was here — the little glyph on a rail item that left this service for
   the portal. Billing no longer links to the portal from anywhere (see the
   Users-section note in shell.js), so there is no such item to mark. */


/* ═══ THE REFERENCE SHELL (2026-08-27) ═══════════════════════════════════════
   The operator's ruling: EVERY page wears the reference panel's chrome — the
   dark accordion rail with the ID/Username/IP search, and the white top strip
   with the logo box, identity, shield and icon row — the same dress as the
   standalone dashboard.html. These rules land after the old shell styles on
   purpose: same selectors later in the file override them, and the old bar's
   own children (.sn-crumb, .sn-topsearch, .sn-user) are retired here rather
   than deleted from twenty templates. shell.js renders the new rail (sn2-*)
   and injects the new strip. */

/* the rail */
.sn-side { width: 237px; background: #343a47; border-right: 0; }
.sn-brand, .sn-sideuser, .sn-home { display: none; }
.sn2-search { display: flex; padding: 12px 10px 12px 0; }
.sn2-search input {
  flex: 1; min-width: 0; height: 34px; border: 0; border-radius: 0;
  padding: 0 8px; font-size: 13px; color: #333; background: #fff; outline: none;
}
.sn2-search input::placeholder { color: #9aa0a6; }
.sn2-search { padding-top: 8px !important; }
/* the brand mark: top of the rail, above the search box, inside the navbar,
   flush with its left/right edges — the operator's asks (2026-08-27, several
   passes). The card's ground is the rail's own colour, not a white box, so
   the mark is retinted (green loop / light lime-green signal, transparent
   ground — assets/brand-mark.png) and the wordmark is light-on-dark to stay
   legible on it. */
.sn2-brand {
  margin: 6px 10px 0 0; padding: 4px 4px 5px; background: #343a47;
}
.sn2-brand a { display: flex; flex-direction: column; align-items: center; gap: 0; }
.sn2-brand img { display: block; max-width: 100%; height: auto; }
.sn2-brand .bw { font-size: 12.5px; font-family: Arial, sans-serif; letter-spacing: .2px; margin-top: -2px; }
.sn2-brand .bw1 { color: #e7eaee; font-weight: 700; }
.sn2-brand .bw2 { color: #b0e228; font-weight: 800; }
.sn2-brand .bt {
  font-size: 5.5px; color: #8a90a0; letter-spacing: 1px;
  text-transform: uppercase; margin-top: 2px; white-space: nowrap;
}
.sn2-search button {
  width: 40px; height: 34px; border: 0; background: #2d9cf0; color: #fff;
  display: grid; place-items: center; flex: none; cursor: pointer;
}
.sn2-search button:hover { background: #1e8ce0; }
.sn2-nav { display: flex; flex-direction: column; }
.sn2-p {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 13px 12px 13px 16px; background: none; border: 0; cursor: pointer;
  text-align: left; font-family: inherit;
  color: #c3c9d4; font-size: 13px; letter-spacing: .4px;
  border-bottom: 1px solid rgba(255,255,255,.05);
  border-left: 3px solid transparent;
}
.sn2-p:hover { background: #2d323e; color: #fff; }
.sn2-p.on { background: #2d323e; color: #fff; border-left-color: #2d9cf0; }
.sn2-p svg { width: 16px; height: 16px; flex: none; opacity: .85; }
.sn2-p .lbl {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; text-transform: uppercase;
}
.sn2-p .sq {
  width: 9px; height: 9px; border: 1px solid rgba(255,255,255,.28);
  border-radius: 2px; flex: none; transition: transform .15s ease;
}
.sn2-p[aria-expanded="true"] .sq { transform: rotate(45deg); border-color: rgba(255,255,255,.6); }
.sn2-sub { background: #2a2e39; border-bottom: 1px solid rgba(255,255,255,.05); }
.sn2-sub[hidden] { display: none; }
.sn2-sub a {
  display: block; padding: 9px 12px 9px 46px;
  color: #aab1bf; font-size: 12.5px; text-decoration: none;
}
.sn2-sub a:hover { background: #262a34; color: #fff; }
.sn2-sub a.is-active { background: #262a34; color: #fff; box-shadow: inset 3px 0 0 #2d9cf0; }

/* the top strip */
.sn-top { min-height: 84px; gap: 14px; padding: 0 18px 0 10px; }
.sn-crumb, .sn-topsearch, .sn-user { display: none !important; }
.sn-burger { color: #555; }
@media (min-width: 901px) { .sn-burger { display: inline-flex; } }
.sn2-ident { display: flex; align-items: center; gap: 9px; white-space: nowrap; color: #222; font-size: 14.5px; }
.sn2-ident b { font-size: 15px; }
.sn2-bal { font-size: 15px; }
.sn2-shield { position: relative; display: inline-grid; place-items: center; }
.sn2-badge {
  position: absolute; top: -6px; right: -8px;
  background: #e53935; color: #fff; font-style: normal; font-size: 10.5px;
  min-width: 16px; height: 16px; line-height: 16px; text-align: center;
  border-radius: 8px; padding: 0 3px; font-weight: 700;
}
.sn2-badge[hidden] { display: none; }
.sn2-tools { margin-left: auto; display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.sn2-tools a { display: grid; place-items: center; padding: 6px; color: #8d939c; }
.sn2-tools a:hover { color: #333; }
.sn2-tools a.grid { color: #4caf50; }
.sn2-tools a.grid:hover { color: #2e7d32; }
.sn2-logout {
  display: flex !important; align-items: center; gap: 5px;
  color: #6d737c !important; font-size: 14px; padding: 6px 2px 6px 8px !important;
  text-decoration: none;
}
.sn2-logout:hover { color: #222 !important; }

/* rail behaviour: on desktop the burger HIDES the rail (the reference has no
   74px icon strip); below 901px the existing drawer + scrim rules apply
   unchanged. The old icon-strip rules above are inert once the rail is
   display:none. */
@media (min-width: 901px) {
  .sn-shell.nav-collapsed .sn-side { display: none; }
}
@media (max-width: 900px) {
  .sn-side { width: 237px; }
  .sn2-ident { flex-wrap: wrap; }
}


/* ═══ BLACK + LIME THEME (2026-08-28) ═══════════════════════════════════════
   Operator's ask: the rail and the top strip black; the page a light
   lime-green / white mix; the type black. Layered here, at the very end of the
   file, so it wins over BOTH the base shell and the reference-shell block
   above — no earlier rule is edited.

   ── Dialled back 2026-08-28 ("lime color ta beshi hoye geche ... white beshi
   use koro"). The first pass tinted every SURFACE lime — the page, the
   hairlines, the table headers, every hover — so the accent was doing the work
   of a background and stopped reading as an accent at all.

   Now lime is only ever on something you ACT on or something that is ON: the
   primary button, the current page in the rail, a live count badge, a link,
   the search button. Every surface behind those is white or a neutral grey.
   The rail and the strip stay black, which is what carries the identity.

   Three colours, and where each is allowed:
     BLACK   #06043d   the rail and the top strip      (hairline #1d1b63)
     LIME    #f39a2b   the accent ON BLACK — active nav row, search button,
                       the balance figure, the grid shortcut
             #0a5fa8   the same accent where it lands on white and has to
                       stay readable — links, primary-on-white, the focus ring
     CANVAS  #fafafa   the page behind the cards        (cards stay #ffffff)
     INK     #141414   body copy and every heading                          */

:root {
  --sn-page:       #fafafa;
  --sn-card:       #ffffff;
  --sn-ink:        #141414;
  --sn-ink-soft:   #3d3d3d;
  /* Neutral greys, not olive ones. These three are the reason the old build
     read as green everywhere: --sn-line paints every card edge, every table
     rule and every input border on the platform. */
  --sn-muted:      #6d716b;
  --sn-line:       #e7e8e6;
  --sn-line-soft:  #f3f4f2;
  --sn-primary:    #0a5fa8;
  --sn-primary-dk: #06043d;
  --sn-accent:     #0a5fa8;
  --sn-teal:       #0a5fa8;
  --sn-focus:      #0a5fa8;
  --sn-header:     #06043d;
  --sn-header-ink: #ededed;
  --sn-side:       #06043d;
  --sn-side-2:     #06043d;
  --sn-side-ink:   #ececec;
  --sn-side-muted: #8b8b8b;
}

/* ── the rail, black ──────────────────────────────────────────────────── */
.sn-side { background: #06043d; border-right: 1px solid #1d1b63; }
.sn2-brand { background: #06043d; }
.sn2-brand .bw1 { color: #f1f1f1; }
.sn2-brand .bw2 { color: #f39a2b; }
.sn2-brand .bt  { color: #7c7c7c; }
.sn2-search input { background: #ffffff; color: #222222; }
.sn2-search button { background: #f39a2b; color: #06043d; }
.sn2-search button:hover { background: #f7ad4f; }
.sn2-p { color: #c8c8c8; border-bottom-color: rgba(255,255,255,.06); }
.sn2-p:hover { background: #15135a; color: #ffffff; }
.sn2-p.on { background: #15135a; color: #f39a2b; border-left-color: #f39a2b; }
.sn2-p .sq { border-color: rgba(255,255,255,.30); }
.sn2-p[aria-expanded="true"] .sq { border-color: #f39a2b; }
.sn2-sub { background: #141414; border-bottom-color: rgba(255,255,255,.06); }
.sn2-sub a { color: #a2a2a2; }
.sn2-sub a:hover { background: #15135a; color: #ffffff; }
.sn2-sub a.is-active { background: #15135a; color: #f39a2b; box-shadow: inset 3px 0 0 #f39a2b; }

/* ── the top strip, black ─────────────────────────────────────────────── */
.sn-top { background: #06043d; border-bottom: 1px solid #1d1b63; }
.sn-burger { color: #cfcfcf; }
.sn-burger:hover { background: #15135a; color: #ffffff; }
.sn2-ident { color: #e9e9e9; }
.sn2-ident b { color: #ffffff; }
.sn2-ident svg[stroke="#f57c00"] { stroke: #f39a2b; }   /* the leading arrow */
.sn2-ident svg[fill="#555"] { fill: #9c9c9c; }           /* the "users" glyph */
.sn2-bal, .sn2-bal b { color: #f39a2b; }
.sn2-tools a { color: #9a9a9a; }
.sn2-tools a:hover { color: #ffffff; }
.sn2-tools a.grid { color: #f39a2b; }
.sn2-tools a.grid:hover { color: #f7ad4f; }
.sn2-logout { color: #b3b3b3 !important; }
.sn2-logout:hover { color: #ffffff !important; }

/* ── the page: white cards on a near-white ground, black type ─────────── */
body { background: var(--sn-page); color: var(--sn-ink); }
.sn-pagehead h1, .sn-card-h h2, .sn-group-title, .sn-form-sec h3, .sn-sub-h,
.sn-emptybox h3, .sn-modal-h h2, .sn-panel-h h2, .sn-kpi-fig, .sn-ministat .v,
.sn-stat .v, .sn-kv b, .sn-kpi-fig { color: #141414; }

/* The primary button keeps the full-strength lime. It is the ONE loud thing
   per screen and the only place the brand colour has a job to do — with every
   surface behind it now neutral, it reads as the action rather than as more
   background. Its hover state is a plain grey, not a tinted one. */
.sn-btn.primary { background: #f39a2b; border-color: #f39a2b; color: #06043d; }
.sn-btn.primary:hover { background: #e08a1c; border-color: #e08a1c; }
.sn-btn:hover { background: #f4f5f3; }

/* Table furniture is grey now. A header band and a row hover are surfaces —
   they say "this is a table", not "look here" — and tinting them was most of
   what made the old build read green. */
.dt-table thead th { background: #f5f6f4; }
.dt-table th.sortable:hover { background: #edeeeb; }
.dt-table tbody tr:hover td { background: #f8f9f7; }
.dt-pager button:hover:not(:disabled) { background: #f2f3f1; }
/* the CURRENT page is a state, so it keeps the accent */
.dt-pager button.is-current { background: #0a5fa8; border-color: #0a5fa8; color: #ffffff; }
.sn-group-h:hover { background: #f7f8f6; }
.sn-stat.is-total { background: #f4f5f2; }
.sn-stat.is-total .v { color: #06043d; }
.sn-toast { border-left-color: #f39a2b; }

/* Page-scoped data tables (All User List, Device List, Reseller Rates, ZONE
   Summary) carry a SOLID header straight from the reference panel — teal
   originally, then the theme's deep lime. A saturated bar the full width of a
   sixteen-column table is the single largest block of colour on the platform,
   which is exactly what "lime beshi hoye geche" was pointing at.
   It is a light grey band with black type now, and the accent survives as the
   2px rule under it: the header still reads as a header, and the colour is a
   line rather than a field. */
.au th, .rr th {
  background: #f4f5f2 !important;
  color: #141414 !important;
  border-right-color: #e7e8e6 !important;
  border-bottom: 2px solid #f39a2b !important;
}
.au tr:nth-child(even) td, .rr tr:nth-child(even) td { background: #fafafa !important; }
.au tr:hover td { background: #f2f3f1 !important; }
.zs-tot { border-top-color: #0a5fa8 !important; }
.zs-tot .v { color: #141414 !important; }


/* ═══ TOP-STRIP ICON ROW (2026-08-28) ══════════════════════════════════════
   The operator's ask: the icon shortcuts sit on ONE horizontal line that
   scrolls sideways rather than wrapping, and each shows its name on hover, on
   keyboard focus, or on a first tap (shell.js positions .sn2-tip). Two of the
   icons — Pending Tickets and Ticket Dashboard — carry a live count. */
.sn2-tools {
  flex-wrap: nowrap; min-width: 0; flex-shrink: 1;
  overflow-x: auto; overflow-y: visible;
  padding: 11px 11px 6px; gap: 7px;
  scrollbar-width: none; -ms-overflow-style: none;
}
.sn2-tools::-webkit-scrollbar { display: none; }
.sn2-tools > a { flex: none; position: relative; padding: 7px; }
/* Bigger glyphs, one rule (2026-08-28: "icon gula aktu boro koro"). Each SVG
   carries its own width/height ATTRIBUTES; a CSS width/height outranks those,
   so the whole row scales here rather than in fifteen separate tags — and a
   future icon inherits the size instead of arriving at the old one. */
.sn2-tools > a svg { width: 22px; height: 22px; }

.sn2-tbadge {
  position: absolute; top: -1px; right: -3px;
  min-width: 15px; height: 15px; padding: 0 3px; border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  font: 800 9.5px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  font-style: normal; letter-spacing: -.02em;
  background: #e0554b; color: #ffffff;                 /* pending — needs attention */
  box-shadow: 0 0 0 2px #06043d;
}
.sn2-tbadge.ratio {
  background: #1d1b63; color: #f39a2b; padding: 0 4px;
  box-shadow: 0 0 0 2px #06043d, inset 0 0 0 1px #3d3d3d;
}
.sn2-tbadge[hidden] { display: none; }

.sn2-tip {
  position: fixed; transform: translateX(-50%); z-index: 200;
  padding: 5px 9px; border-radius: 7px;
  background: #1c1c1c; color: #f1f1f1; border: 1px solid #383838;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .5);
  font: 600 11px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  white-space: nowrap; max-width: 60vw; overflow: hidden; text-overflow: ellipsis;
  opacity: 0; pointer-events: none; transition: opacity .12s ease;
}
.sn2-tip.on { opacity: 1; }

/* keep it one line on the narrow layout too — the sideways scroll is the point */
@media (max-width: 900px) {
  .sn2-tools { flex-wrap: nowrap; }
}

/* ===== Full-width, big tables on every billing page (operator, 2026-09-24:
   "mobile log ar moto protita page ar view ar table amon boro koro ... billing
   jekhane jekhane table ache"). Same recipe the Mobile Banking Log proved:
   - a page that holds a table drops the 1400px cap and the side gutters;
   - table text scales with the screen, 16px on a ~1930px-wide screen down to
     a 12px floor, so a wide grid still fits a laptop instead of pushing its
     last columns off the edge.
   Excluded on purpose: the customer details sheet (a fixed-width maXim
   replica) and the small label/value form tables. Specificity is raised with
   the :not() chain so it wins over each page's own `.x-table td` rule. */
.sn-content:has(table) { max-width: none; padding-left: 6px; padding-right: 6px; }
.cp-wrap, .lm-wrap, .ft-box, .bc-page, .bxl { max-width: none !important; }
.sn-content table:not(.cd-table):not(.cd-htable):not(.bc-form):not(.am):not(.st-tbl):not(.cp-tip) :is(td, th) {
  font-size: clamp(12px, 0.83vw, 16px);
}
/* Grids that still pushed columns off the edge because their cells are held
   on one line: let them wrap at spaces like DataTables' own cells, and on a
   laptop-sized screen let long unbroken ids / phone numbers split too, so
   every column stays on screen. Numeric cells stay whole. */
.sn-content :is(table.cp-table, table.ou-table, table.pp, table.rl2, table.dt-table, table.pkl, table.mx, table.au, table.mx-table) :is(td, th) {
  white-space: normal;
}
@media (max-width: 1699px) {
  .sn-content :is(table.cp-table, table.ou-table, table.pp, table.rl2, table.dt-table, table.pkl, table.mx, table.au, table.mx-table) td {
    overflow-wrap: anywhere;
  }
}
.sn-content table :is(td, th):is(.num, .n, .r) { white-space: nowrap; overflow-wrap: normal; }

/* Udayan Online: light logo corner in the logo's greens */
.sn2-brand { background: #ffffff !important; border-bottom: 3px solid transparent !important; border-image: linear-gradient(90deg, #06043d, #0a5fa8 45%, #0a92c8 70%, #e30d0d 90%, #f39a2b) 1 !important; padding-top: 8px !important; padding-bottom: 8px !important; }
.sn2-brand .bw1 { color: #06043d !important; }
.sn2-brand .bw2 { color: #0a5fa8 !important; }
.sn2-brand .bt { color: #0b1a5c !important; }

/* Udayan Online: no role text beside the name */
.sn2-top .pid, .pid { display: none !important; }

/* Udayan Online: top strip = the portal's (white, SpaceNet gradient line, navy ink) */
.sn-top { background: #ffffff !important; border-bottom: 0 !important; box-shadow: 0 2px 8px rgba(6,4,61,.10) !important; position: relative; }
.sn-top::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: linear-gradient(90deg, #06043d, #0a5fa8 45%, #0a92c8 70%, #e30d0d 90%, #f39a2b); pointer-events: none; }
.sn-top .sn-burger, .sn-burger { color: #06043d !important; }
.sn-burger:hover { background: #eef4fb !important; color: #0a5fa8 !important; }
.sn2-ident, .sn2-ident b, .sn-user, .sn-user-name, .sn-crumb, .sn-crumb a { color: #06043d !important; }
.sn2-ident svg[stroke="#f57c00"] { stroke: #e30d0d !important; }
.sn2-tools a, .sn-top .sn-iconbtn, .sn-top a { color: #0a5fa8 !important; }
.sn2-tools a:hover, .sn-top a:hover { color: #06043d !important; }
.sn2-logout { color: #06043d !important; }
.sn-btn.primary { background: #0a5fa8 !important; border-color: #0a5fa8 !important; color: #fff !important; }
.sn-btn.primary:hover { background: #06043d !important; border-color: #06043d !important; }
body { background: #f4f4f6; }

/* Udayan Online: identity readable on the white strip */
.sn2-who-name, .sn2-who b { color: #06043d !important; }
.sn2-who-role, .sn2-who-dept { color: #5d6680 !important; }
.db-ident, .db-ident .pid, .db-ident b { color: #06043d !important; }
.sn2-brand img.ud-wordmark { width: 200px !important; max-width: 100% !important; height: auto !important; display: block; margin: 0 auto; }
.sn2-brand .bt { margin-top: 2px; }
.sn2-sub { background: #0b0948 !important; }
.sn2-sub a:hover, .sn2-sub a.is-active { background: #15135a !important; }

/* Udayan Online: every navbar soft charcoal (user: "halka black ... grey black better"), orange = current */
.sn-side, .db-side { background: #2b2f36 !important; border-right: 1px solid #3a3f48 !important; box-shadow: 2px 0 8px rgba(0,0,0,.08); }
.sn2-search, .db-search { background: #2b2f36 !important; }
.sn2-search input, .db-search input { background: #ffffff !important; color: #06043d !important; border: 0 !important; }
.sn2-search button, .db-search button { background: #f39a2b !important; color: #ffffff !important; }
.sn2-search button:hover, .db-search button:hover { background: #e08a1c !important; }
.sn2-p, .db-nav-p { color: #e4e7ec !important; border-bottom-color: rgba(255,255,255,.06) !important; background: transparent !important; }
.sn2-p svg, .db-nav-p svg { color: #c3c9d4 !important; }
.sn2-p:hover, .db-nav-p:hover { background: #363b44 !important; color: #ffffff !important; }
.sn2-p.on, .db-nav-p.on { background: #363b44 !important; color: #f39a2b !important; border-left-color: #f39a2b !important; }
.sn2-p .sq, .db-nav-p .sq { border-color: rgba(255,255,255,.35) !important; }
.sn2-p[aria-expanded="true"] .sq, .db-nav-p.open .sq { border-color: #f39a2b !important; }
.sn2-sub, .db-sub { background: #23262c !important; border-bottom-color: rgba(255,255,255,.05) !important; }
.sn2-sub a, .db-sub a { color: #b9c0cc !important; }
.sn2-sub a:hover, .db-sub a:hover { background: #31353d !important; color: #ffffff !important; }
.sn2-sub a.is-active, .db-sub a.is-active, .db-sub a.on { background: #31353d !important; color: #f39a2b !important; box-shadow: inset 3px 0 0 #f39a2b !important; }
.sn-side::-webkit-scrollbar-thumb { background: #4a505b !important; }

/* Udayan Online: top bars soft charcoal like the left menus */
.pt-nav, .topnav, .sn-top, .db-top { background: #2b2f36 !important; color: #e4e7ec !important; box-shadow: 0 2px 8px rgba(0,0,0,.18) !important; }
.pt-greet, .pt-brand { color: #e4e7ec !important; }
.pt-burger, .pt-out, .pt-nav .pt-out, .sn-burger, .sn-top .sn-burger, .db-burger, .db-top .db-burger { color: #e4e7ec !important; }
.pt-nav .sk-round, .pt-nav .pt-out { background: #363b44 !important; border: 1px solid #4a505b !important; box-shadow: none !important; color: #ffffff !important; }
.pt-nav .sk-round:hover { background: #41474f !important; color: #f39a2b !important; }
.sn2-ident, .sn2-ident b, .sn2-who-name, .sn2-who b, .db-ident, .db-ident b, .db-ident .pid, .sn-user, .sn-user-name, .sn-crumb, .sn-crumb a { color: #ffffff !important; }
.sn2-who-role, .sn2-who-dept { color: #aeb5c1 !important; }
.sn2-tools a, .sn-top .sn-iconbtn, .sn-top a, .db-top a, .db-top .sn-iconbtn, .sn2-logout, .db-logout { color: #d6dbe3 !important; }
.sn2-tools a:hover, .sn-top a:hover, .db-top a:hover { color: #f39a2b !important; }
.sn-burger:hover, .pt-burger:hover { background: #363b44 !important; color: #ffffff !important; }
.topnav .tn-search input { background: #363b44 !important; border-color: #4a505b !important; color: #ffffff !important; }
.topnav .tn-search input::placeholder { color: #aeb5c1 !important; }
.topnav .tn-btn, .topnav .tn-pill, .topnav .tn-mode button, .topnav .tk-flag { color: #e4e7ec !important; border-color: #4a505b !important; }
.topnav .tn-mode { border-color: #4a505b !important; }
.topnav .tn-btn:hover, .topnav .tn-pill:hover, .topnav .tn-mode button:hover { background: #363b44 !important; color: #ffffff !important; }
.topnav .tn-brand:hover, .topnav .tn-brand[aria-expanded="true"] { background: #363b44 !important; border-color: #4a505b !important; }
.sn2-brand, .db-brand { background: #2b2f36 !important; }

.sn2-brand img, .db-brand img { content: url("/portal/billing/assets/udayan-logo-light.png"); }
