/*
 * SMSMetro design system.
 *
 * Tokens are lifted from the Claude Design mockup; the SCALES are consolidated.
 * The mockup used 30 distinct font sizes (10.5px, 13.5px, 16.5px...) and 14
 * radii, which is normal for a visual comp and unworkable in a codebase: nothing
 * lines up, and every new screen invents its own values. Twelve type steps and
 * five radii reproduce the same design while making inconsistency visible.
 */

/* ---------------------------------------------------------------- tokens */
:root {
  /* surfaces */
  --bg: #f6f7f9;
  --surface: #ffffff;
  --surface-2: #f1f3f6;
  --surface-3: #e9edf2;
  --border: #e4e7ec;
  --border-strong: #d6dae1;

  /* text */
  --text: #0c1220;
  --text-2: #525b6b;
  --text-3: #8a93a2;

  /* brand + status */
  --primary: #1e40af;
  --primary-2: #2952d6;
  --primary-weak: #eef2ff;
  --on-primary: #ffffff;
  --success: #059669;
  --success-weak: #e7f6ef;
  --warning: #c2760a;
  --warning-weak: #fbf1e0;
  --danger: #dc2626;
  --danger-weak: #fbeaea;

  /* elevation */
  --shadow-sm: 0 1px 2px rgba(16, 24, 40, .05);
  --shadow: 0 1px 3px rgba(16, 24, 40, .08), 0 1px 2px rgba(16, 24, 40, .05);
  --shadow-lg: 0 12px 32px -8px rgba(16, 24, 40, .14), 0 4px 8px -4px rgba(16, 24, 40, .08);
  --shadow-xl: 0 24px 60px -12px rgba(16, 24, 40, .22);

  /* type scale — 12 steps, no half pixels */
  --fs-2xs: 11px;
  --fs-xs: 12px;
  --fs-sm: 13px;
  --fs-base: 14px;
  --fs-md: 15px;
  --fs-lg: 16px;
  --fs-xl: 18px;
  --fs-2xl: 20px;
  --fs-3xl: 24px;
  --fs-4xl: 30px;
  --fs-5xl: 38px;
  --fs-6xl: 48px;

  /* spacing — 4px base */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 20px; --sp-6: 24px; --sp-8: 32px; --sp-10: 40px; --sp-12: 48px;

  /* radii — 5 steps */
  --r-sm: 6px;
  --r: 8px;
  --r-md: 10px;
  --r-lg: 14px;
  --r-full: 999px;

  --sidebar-w: 232px;
  --header-h: 60px;
}

.dark {
  --bg: #080a0e;
  --surface: #101319;
  --surface-2: #161a21;
  --surface-3: #1d222b;
  --border: #232833;
  --border-strong: #2e343f;
  --text: #f2f4f8;
  --text-2: #a3adbb;
  --text-3: #697182;
  --primary: #4f7cf7;
  --primary-2: #6b90f8;
  --primary-weak: #15213c;
  --success: #34d399;
  --success-weak: #0f2a22;
  --warning: #f0b429;
  --warning-weak: #2c2411;
  --danger: #f87171;
  --danger-weak: #2c1616;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow: 0 1px 3px rgba(0, 0, 0, .5);
  --shadow-lg: 0 12px 32px -8px rgba(0, 0, 0, .6);
  --shadow-xl: 0 24px 60px -12px rgba(0, 0, 0, .7);
}

/* ------------------------------------------------------------- baseline */
*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-size: var(--fs-base);
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  letter-spacing: -0.011em;
  min-height: 100vh;
  transition: background .25s, color .25s;
}

::selection { background: var(--primary-weak); }
a { color: var(--primary); text-decoration: none; }
a:hover { color: var(--primary-2); }
.mono { font-family: 'JetBrains Mono', ui-monospace, monospace; }
i[data-lucide] { width: 1em; height: 1em; stroke-width: 2; display: inline-block; vertical-align: -0.125em; }
img { max-width: 100%; height: auto; }

/* Respect the OS setting: motion can be genuinely disabling, and none of
   these animations carry information that the static state does not. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* ----------------------------------------------------------- animations */
@keyframes fadeUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes pulsering {
  0%   { box-shadow: 0 0 0 0 rgba(5, 150, 105, .5); }
  70%  { box-shadow: 0 0 0 6px rgba(5, 150, 105, 0); }
  100% { box-shadow: 0 0 0 0 rgba(5, 150, 105, 0); }
}
@keyframes flashin {
  0%   { opacity: 0; transform: translateY(-6px); background: var(--primary-weak); }
  100% { opacity: 1; transform: none; background: transparent; }
}
@keyframes shimmer { 0% { background-position: -360px 0; } 100% { background-position: 360px 0; } }

.fade-up { animation: fadeUp .5s cubic-bezier(.16, .84, .44, 1) both; }
.flash-in { animation: flashin .8s ease-out both; }

/* A pulsing dot for genuinely live data. Used sparingly: if everything
   pulses, nothing reads as live. */
.livedot {
  width: 7px; height: 7px; border-radius: var(--r-full);
  background: var(--success); animation: pulsering 2s infinite;
  display: inline-block; flex: none;
}

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

.sidebar {
  width: var(--sidebar-w); flex: none;
  background: var(--surface); border-right: 1px solid var(--border);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
}

.sidebar-brand {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-5);
  font-size: var(--fs-md); font-weight: 700;
  border-bottom: 1px solid var(--border);
  height: var(--header-h);
}

.sidebar-nav { padding: var(--sp-3) var(--sp-3); overflow-y: auto; flex: 1; }

.nav-section {
  font-size: var(--fs-2xs); font-weight: 600; color: var(--text-3);
  text-transform: uppercase; letter-spacing: .04em;
  padding: var(--sp-4) var(--sp-3) var(--sp-2);
}

.navbtn {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 9px var(--sp-3); border-radius: var(--r);
  font-size: var(--fs-sm); font-weight: 500; color: var(--text-2);
  transition: background .12s, color .12s;
}
.navbtn:hover { background: var(--surface-2); color: var(--text); }
.navbtn.active { background: var(--primary-weak); color: var(--primary); font-weight: 600; }
.navbtn .badge { margin-left: auto; }

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

.topbar {
  height: var(--header-h); flex: none;
  display: flex; align-items: center; gap: var(--sp-4);
  padding: 0 var(--sp-6);
  background: var(--surface); border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 20;
}

.page { padding: var(--sp-6); flex: 1; }
.page-title { font-size: var(--fs-2xl); font-weight: 700; margin: 0; }
.page-sub { font-size: var(--fs-sm); color: var(--text-2); margin: var(--sp-1) 0 0; }

/* ----------------------------------------------------------- components */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--shadow-sm);
}
.card-pad { padding: var(--sp-5); }
.card-head {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-md); font-weight: 700;
}

.kpi { padding: var(--sp-5); }
.kpi-label { font-size: var(--fs-sm); color: var(--text-2); }
.kpi-value { font-size: var(--fs-3xl); font-weight: 700; margin-top: var(--sp-1); line-height: 1.15; }
.kpi-hint { font-size: var(--fs-xs); color: var(--text-3); margin-top: var(--sp-1); }

.grid { display: grid; gap: var(--sp-4); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  padding: 9px var(--sp-4); border-radius: var(--r);
  font-size: var(--fs-sm); font-weight: 600; font-family: inherit;
  border: 1px solid transparent; cursor: pointer;
  transition: background .12s, border-color .12s, opacity .12s;
}
.btn-primary { background: var(--primary); color: var(--on-primary); }
.btn-primary:hover { background: var(--primary-2); color: var(--on-primary); }
.btn-secondary { background: var(--surface); border-color: var(--border-strong); color: var(--text-2); }
.btn-secondary:hover { background: var(--surface-2); color: var(--text); }
.btn-ghost { background: transparent; color: var(--text-2); }
.btn-ghost:hover { background: var(--surface-2); }
.btn-danger { background: var(--danger); color: #fff; }
.btn-sm { padding: 6px var(--sp-3); font-size: var(--fs-xs); }
.btn-lg { padding: var(--sp-3) var(--sp-5); font-size: var(--fs-base); }
.btn-block { width: 100%; }
.btn:disabled, .btn[disabled] { opacity: .5; cursor: not-allowed; }

.input, .select {
  width: 100%; padding: 9px var(--sp-3);
  border: 1px solid var(--border-strong); border-radius: var(--r);
  background: var(--surface); color: var(--text);
  font-size: var(--fs-sm); font-family: inherit;
}
.input:focus, .select:focus {
  outline: none; border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-weak);
}
.label {
  display: block; font-size: var(--fs-2xs); font-weight: 600;
  color: var(--text-3); text-transform: uppercase; letter-spacing: .04em;
  margin-bottom: var(--sp-2);
}
.hint { font-size: var(--fs-xs); color: var(--text-3); margin-top: var(--sp-1); }
.field-error { font-size: var(--fs-xs); color: var(--danger); margin-top: var(--sp-1); }

.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px var(--sp-2); border-radius: var(--r-sm);
  font-size: var(--fs-2xs); font-weight: 600;
}
.badge-neutral { background: var(--surface-3); color: var(--text-2); }
.badge-success { background: var(--success-weak); color: var(--success); }
.badge-warning { background: var(--warning-weak); color: var(--warning); }
.badge-danger  { background: var(--danger-weak);  color: var(--danger); }
.badge-primary { background: var(--primary-weak); color: var(--primary); }

.table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.table th {
  text-align: left; font-weight: 600; color: var(--text-2);
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .03em;
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface-2); border-bottom: 1px solid var(--border);
}
.table td { padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border); }
.table tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--surface-2); }
.table-wrap { overflow-x: auto; border-radius: var(--r-lg); border: 1px solid var(--border); background: var(--surface); }

.alert { padding: var(--sp-3) var(--sp-4); border-radius: var(--r); border: 1px solid; font-size: var(--fs-sm); }
.alert-success { background: var(--success-weak); border-color: var(--success); color: var(--success); }
.alert-warning { background: var(--warning-weak); border-color: var(--warning); color: var(--warning); }
.alert-danger  { background: var(--danger-weak);  border-color: var(--danger);  color: var(--danger); }
.alert-info    { background: var(--primary-weak); border-color: var(--primary); color: var(--primary); }

/* An empty state should say what to do next, not merely that there is
   nothing here — otherwise the user is left to guess. */
.empty {
  text-align: center; padding: var(--sp-12) var(--sp-6);
  border: 1px dashed var(--border-strong); border-radius: var(--r-lg);
  background: var(--surface);
}
.empty-icon { font-size: var(--fs-4xl); color: var(--text-3); }
.empty-title { font-size: var(--fs-md); font-weight: 600; margin: var(--sp-3) 0 var(--sp-1); }
.empty-body { font-size: var(--fs-sm); color: var(--text-2); max-width: 380px; margin: 0 auto var(--sp-4); }

/* Skeletons match the shape of the content they replace, so the layout does
   not jump when real data arrives. */
.skeleton {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%);
  background-size: 720px 100%;
  animation: shimmer 1.4s infinite linear;
  border-radius: var(--r-sm);
}
.skeleton-line { height: 12px; margin-bottom: var(--sp-2); }
.skeleton-line:last-child { width: 60%; margin-bottom: 0; }

.spinner {
  width: 16px; height: 16px; border-radius: var(--r-full);
  border: 2px solid var(--border-strong); border-top-color: var(--primary);
  animation: spin .7s linear infinite; display: inline-block;
}

.modal-backdrop {
  position: fixed; inset: 0; background: rgba(12, 18, 32, .45);
  display: grid; place-items: center; padding: var(--sp-4); z-index: 50;
}
.modal {
  background: var(--surface); border-radius: var(--r-lg);
  box-shadow: var(--shadow-xl); width: 100%; max-width: 480px;
}
.modal-head { padding: var(--sp-5); border-bottom: 1px solid var(--border); font-size: var(--fs-lg); font-weight: 700; }
.modal-body { padding: var(--sp-5); }
.modal-foot { padding: var(--sp-4) var(--sp-5); border-top: 1px solid var(--border); display: flex; justify-content: flex-end; gap: var(--sp-2); }

.code-block {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r); padding: var(--sp-3) var(--sp-4);
  font-family: 'JetBrains Mono', monospace; font-size: var(--fs-xs);
  overflow-x: auto; color: var(--text-2);
}

/* -------------------------------------------------------------- helpers */
.stack { display: flex; flex-direction: column; }
.row { display: flex; align-items: center; }
.gap-1 { gap: var(--sp-1); } .gap-2 { gap: var(--sp-2); } .gap-3 { gap: var(--sp-3); } .gap-4 { gap: var(--sp-4); }
.mt-2 { margin-top: var(--sp-2); } .mt-4 { margin-top: var(--sp-4); } .mt-6 { margin-top: var(--sp-6); } .mt-8 { margin-top: var(--sp-8); }
.mb-2 { margin-bottom: var(--sp-2); } .mb-4 { margin-bottom: var(--sp-4); } .mb-6 { margin-bottom: var(--sp-6); }
.ml-auto { margin-left: auto; }
.text-2 { color: var(--text-2); } .text-3 { color: var(--text-3); }
.text-success { color: var(--success); } .text-danger { color: var(--danger); } .text-warning { color: var(--warning); }
.fs-xs { font-size: var(--fs-xs); } .fs-sm { font-size: var(--fs-sm); } .fs-lg { font-size: var(--fs-lg); } .fs-2xl { font-size: var(--fs-2xl); }
.fw-600 { font-weight: 600; } .fw-700 { font-weight: 700; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hide { display: none !important; }


/* ------------------------------------------------- responsive additions
   Added during screen conversion (Session 016). Two-column asymmetric
   layouts were being built with inline grid-template-columns, which
   overrides the media-query collapse below and pins two columns on
   phones. These classes carry the ratio AND the collapse. */
.grid-split { grid-template-columns: 1.4fr 1fr; }
.grid-split-rev { grid-template-columns: 1fr 1.4fr; }
.menu-btn { display: none; }

/* Public page headers (landing, marketing, docs). The action group must stay
   right-aligned even when the link list is hidden at small widths — an inline
   margin-left here beats .ml-auto and drops the buttons into the middle of the
   bar, which is what happened before this existed. Secondary controls step
   aside on phones so the primary action always fits. */
.nav-actions { margin-left: auto; flex: none; }

/* Mobile purchase bar. On a phone the columns stack, so the order summary and
   its Buy button sit below a service grid that can run thousands of rows —
   the price a customer is about to pay must not require a long scroll to see.
   Desktop keeps the summary card and hides this entirely. */
.buy-bar { display: none; }

/* The service grid can carry thousands of rows. On a phone that pushes the
   offer chooser and the order summary far below the fold — a customer should
   never have to scroll past the whole catalogue to reach the thing they are
   buying. Bound it and let the grid scroll inside itself. */
/* Once a service is chosen the catalogue has done its job. Collapsing it on
   phones brings the offer chooser and the price within a screen instead of
   several — the grid is still one tap away via Change. */
body.service-picked .service-scroll,
body.service-picked #services-empty { display: none; }
body.service-picked .picked-row { display: flex; }
.picked-row { display: none; }

@media (max-width: 820px) {
  .service-scroll {
    max-height: 40vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding-right: 2px;
    border-radius: var(--r);
  }
}
@media (max-width: 820px) {
  .buy-bar {
    display: flex; align-items: center; gap: var(--sp-3);
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 35;
    padding: var(--sp-3) var(--sp-4);
    padding-bottom: calc(var(--sp-3) + env(safe-area-inset-bottom));
    background: var(--surface); border-top: 1px solid var(--border);
    box-shadow: 0 -6px 20px rgba(10, 14, 22, .08);
  }
  .buy-bar .btn { flex: 1; }
  body.has-buy-bar .main { padding-bottom: 96px; }
}
@media (max-width: 560px) {
  .nav-secondary { display: none; }
}
.drawer-backdrop { display: none; position: fixed; inset: 0; background: rgba(10, 14, 22, .45); z-index: 40; }

/* ---------------------------------------------------------- responsive */
@media (max-width: 1080px) and (min-width: 821px) {
  .grid-4 { grid-template-columns: repeat(3, 1fr); }
  .sidebar { width: 68px; }
  .sidebar .navlabel, .sidebar .nav-section, .sidebar .userinfo { display: none; }
  .sidebar .navbtn { justify-content: center; }
  .sidebar-brand span { display: none; }
}

@media (max-width: 820px) {
  .grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .grid-2, .grid-split, .grid-split-rev { grid-template-columns: 1fr; }
  .page { padding: var(--sp-4); }
}

@media (max-width: 560px) {
  /* Phones: KPI-style 4-grids read best two-up (matching the mockup's
     mobile views); 2/3-grids stack. Full single-column for everything
     made dashboards an endless scroll. */
  .grid-2, .grid-3, .grid-split, .grid-split-rev { grid-template-columns: 1fr; }
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .page { padding: var(--sp-3); }
  .grid { gap: var(--sp-3); }
  .kpi { padding: var(--sp-3) var(--sp-4); }
  .kpi-label { font-size: var(--fs-2xs); }
  .kpi-value { font-size: var(--fs-2xl); }
  .kpi-hint { font-size: var(--fs-2xs); }
  .card-head { flex-wrap: wrap; row-gap: var(--sp-2); }
  .card-pad { padding: var(--sp-4); }
  .table th, .table td { padding: var(--sp-2) var(--sp-3); }
  .topbar .userinfo span { display: none; }
  /* Phone topbar carries only menu, title, balance, avatar. */
  .topbar [data-theme-toggle], .topbar .badge { display: none; }
  .topbar { padding: 0 var(--sp-3); }
  .topbar .row.gap-3 { gap: var(--sp-2); }
}

/* Phones and small tablets: navigation is a slide-in drawer behind a
   hamburger. Replaces the earlier bottom tab bar. Full sidebar markup
   (brand, labels, sections, footer) renders inside the drawer. */
@media (max-width: 820px) {
  .sidebar {
    position: fixed; top: 0; left: 0; bottom: 0; z-index: 50;
    width: 272px; transform: translateX(-105%);
    transition: transform .22s ease; box-shadow: var(--shadow-lg);
    display: flex; flex-direction: column;
    padding-bottom: env(safe-area-inset-bottom);
  }
  /* Foot (sign out) stays pinned and reachable: the nav scrolls, not the drawer. */
  .sidebar-nav { flex: 1; min-height: 0; overflow-y: auto; }
  .sidebar-foot { flex: none; }
  .topbar { height: 56px; }
  .topbar > .fw-700 { font-size: var(--fs-md); }
  body.drawer-open .sidebar { transform: translateX(0); }
  body.drawer-open .drawer-backdrop { display: block; }
  body.drawer-open { overflow: hidden; }
  .menu-btn { display: inline-flex; }
}
