@charset "UTF-8";

/* domain-ops design system — "daylight control room"
   ink rail + cool mist canvas; cobalt = control, ember = fire (flagged/burned only)

   Sizing is expressed in rem against --ui-base, so the whole interface scales
   from one number. Hairlines, radii and shadows stay in px on purpose: a 1px
   border is a 1px border at any scale, and scaling it only makes it blurry. */

:root {
  --ui-base: 18px;

  --ink: #1B2733;
  --rail: #101B26;
  --rail-text: #A7B6C2;
  --muted: #5F6E7B;
  --mist: #EDF0F3;
  --panel: #FFFFFF;
  --line: #DCE2E8;
  --line-soft: #E8ECF0;
  --control: #2946D8;
  --control-deep: #1D33A8;
  --control-bg: #E8ECFB;
  --control-line: #C9D3F7;
  --clean: #188A54;
  --clean-bg: #E2F3EA;
  --ember: #D9481F;
  --ember-deep: #B23A17;
  --ember-bg: #FBE9E2;
  --amber: #B87E14;
  --amber-bg: #F8EFD8;
  --neutral-bg: #E9EDF1;
  --radius: 10px;
  --font-ui: "IBM Plex Sans", -apple-system, sans-serif;
  --font-display: "Space Grotesk", var(--font-ui);
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;
  --shadow: 0 1px 2px rgba(16,27,38,.05), 0 8px 24px rgba(16,27,38,.06);
}

* { margin: 0; padding: 0; box-sizing: border-box; }
/* `.btn { display: inline-flex }` outranks the UA rule for [hidden], so a hidden
   button stayed on screen. Everything that hides itself relies on this. */
[hidden] { display: none !important; }
html { -webkit-font-smoothing: antialiased; font-size: var(--ui-base); }
body {
  font-family: var(--font-ui);
  font-size: .875rem; line-height: 1.45;
  color: var(--ink); background: var(--mist);
}
a { color: var(--control); text-decoration: none; }
button { font: inherit; }
:focus-visible { outline: 2px solid var(--control); outline-offset: 2px; }

/* ---------- pointer ----------
   Dense operational tables flip the cursor between arrow, caret and hand on
   every few pixels of travel, which reads as flicker. Two rules only:

     the arrow everywhere,
     the hand on what can be clicked,

   and the caret exclusively inside fields you type into. An earlier version also
   gave the caret to values worth copying (.mono, .domain) — which put an I-beam
   on every email and domain in every table and brought the flicker straight back.
   Selecting text does not need a caret to be possible; user-select is untouched. */
body { cursor: default; }
/* Text fields only — a checkbox is a control, and the caret over one reads as
   "you can type here" on a cell that is only ever clicked. */
input:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]),
textarea, [contenteditable] { cursor: text; }
a[href], button, summary, select, .switch, label[for], th[data-order-by],
input[type=checkbox], input[type=radio], .pick-row, .check,
[data-action], [data-pane-open], [data-tab], [data-popup-close] { cursor: pointer; }
button:disabled, .btn:disabled, select:disabled, input:disabled { cursor: not-allowed; }
th, .table th, label, .kv dt, .chip, .rail-group { user-select: none; }

/* ---------- app frame ---------- */
.app { display: grid; grid-template-columns: 14rem 1fr; min-height: 100vh; }
.main { min-width: 0; }
.content { padding: 1.375rem 1.75rem 3rem; max-width: 77.5rem; }

/* ---------- rail (sidebar) ---------- */
.rail {
  background: var(--rail); color: var(--rail-text);
  padding: 1.125rem 0 1.25rem; display: flex; flex-direction: column; gap: .25rem;
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
.wordmark {
  font-family: var(--font-display); font-weight: 700; font-size: 1.0625rem;
  color: #fff; letter-spacing: .01em;
  padding: .125rem 1.125rem .875rem; display: flex; align-items: center; gap: .5rem;
  border-bottom: 1px solid rgba(255,255,255,.08); margin-bottom: .625rem;
}
.wordmark .flare { width: .625rem; height: .625rem; background: var(--control); }
.rail-group { padding: .625rem 1.125rem .25rem; font-size: .66rem; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: #5D7183; }
.rail a.item {
  display: flex; align-items: center; justify-content: space-between;
  padding: .4375rem 1.125rem .4375rem .9375rem; color: var(--rail-text); font-size: .845rem;
  border-left: 3px solid transparent;
}
.rail a.item:hover { color: #fff; background: rgba(255,255,255,.04); }
.rail a.item.active {
  color: #fff; border-left-color: var(--control);
  background: linear-gradient(90deg, rgba(41,70,216,.22), rgba(41,70,216,0));
}
.rail .count { font-family: var(--font-mono); font-size: .6875rem; color: #5D7183; }
.rail a.item.active .count { color: #9FB0FF; }
.rail-foot { margin-top: auto; padding: .75rem 1.125rem 0; border-top: 1px solid rgba(255,255,255,.08);
  font-size: .75rem; color: #5D7183; }
.rail-foot .health { margin-top: .5rem; }

/* pool health strip */
.health { display: flex; height: .375rem; border-radius: 3px; overflow: hidden; background: #24313D; }
.health i { display: block; height: 100%; }
.health .h-clean { background: var(--clean); }
.health .h-flag { background: var(--ember); }
.health .h-idle { background: #45566577; }

/* ---------- topbar ---------- */
.topbar {
  display: flex; align-items: center; gap: .875rem;
  padding: .875rem 1.75rem; background: var(--panel); border-bottom: 1px solid var(--line);
}
.topbar h1 { font-family: var(--font-display); font-size: 1.1875rem; font-weight: 600; letter-spacing: -.01em; }
.topbar .crumb { color: var(--muted); font-size: .8125rem; }
.topbar .spacer { flex: 1; }
.burger { display: none; border: 1px solid var(--line); background: #fff; border-radius: 8px;
  width: 2.25rem; height: 2.25rem; font-size: 1rem; }
.env {
  font-family: var(--font-mono); font-size: .66rem; letter-spacing: .08em;
  padding: .1875rem .5rem; border-radius: 6px; background: var(--control-bg); color: var(--control-deep);
}
.avatar {
  width: 1.875rem; height: 1.875rem; border-radius: 50%; background: var(--ink); color: #fff;
  font-size: .75rem; font-weight: 600; display: flex; align-items: center; justify-content: center;
  flex: none;
}

/* who is signed in + the way out; the avatar alone signed people out on click */
.user { display: flex; align-items: center; gap: .625rem; }
.user .who { font-size: .8125rem; font-weight: 600; line-height: 1.2; }
.user .who small { display: block; font-weight: 400; color: var(--muted); font-size: .6875rem; }

/* ---------- page head ---------- */
.page-head { display: flex; align-items: flex-end; gap: .875rem; margin: .375rem 0 1rem; flex-wrap: wrap; }
.page-head .sub { color: var(--muted); font-size: .8125rem; max-width: 40rem; }
.page-head .spacer { flex: 1; }

/* ---------- signal flare + tally (signature) ---------- */
.flare {
  display: inline-block; width: .5625rem; height: .5625rem; border-radius: 2.5px;
  transform: rotate(45deg); flex: none;
}
.flare.clean   { background: var(--clean); }
.flare.flagged { background: var(--ember); }
.flare.pending { background: var(--amber); }
.flare.idle    { background: #A9B6C1; }
.tally { display: inline-flex; gap: 2px; align-items: center; }
.tally i { width: .1875rem; height: .6875rem; border-radius: 1px; background: var(--ember); }
.tally .t-label { font-family: var(--font-mono); font-size: .6875rem; color: var(--muted); margin-left: .25rem; }

/* ---------- chips ---------- */
.chip {
  display: inline-flex; align-items: center; gap: .375rem;
  font-size: .72rem; font-weight: 600; letter-spacing: .02em;
  padding: .125rem .5625rem; border-radius: 999px; white-space: nowrap;
}
.chip.clean    { background: var(--clean-bg); color: #106B40; }
.chip.flagged  { background: var(--ember-bg); color: var(--ember-deep); }
.chip.pending  { background: var(--amber-bg); color: #8E6210; }
.chip.neutral  { background: var(--neutral-bg); color: var(--muted); }
.chip.control  { background: var(--control-bg); color: var(--control-deep); }
/* Google has a finding, Safe Browsing is not blocking. Amber like `pending`, but
   outlined: this is a standing state somebody chose to live with, not a step in a
   process that will finish on its own, and the two must not read the same. */
.chip.warn     { background: var(--amber-bg); color: #8E6210; box-shadow: inset 0 0 0 1px currentColor; }
.chip .dot { width: .375rem; height: .375rem; border-radius: 50%; background: currentColor; }

/* ---------- buttons / inputs ---------- */
.btn {
  display: inline-flex; align-items: center; gap: .4375rem;
  font-size: .845rem; font-weight: 600; border-radius: 8px;
  padding: .5rem .875rem; border: 1px solid transparent;
}
.btn.primary { background: var(--control); color: #fff; }
.btn.primary:hover { background: var(--control-deep); }
.btn.ghost { background: #fff; border-color: var(--line); color: var(--ink); }
.btn.ghost:hover { border-color: #B9C4CE; }
.btn.danger { background: #fff; border-color: #F0C4B5; color: var(--ember-deep); }
.btn.danger:hover { background: var(--ember-bg); }
.btn.sm { padding: .3125rem .625rem; font-size: .78rem; border-radius: 7px; }
.btn:disabled { opacity: .55; }
.icon-btn { border: none; background: none; color: var(--muted); font-size: .9375rem; padding: .25rem .375rem; border-radius: 6px; }
.icon-btn:hover { background: var(--neutral-bg); color: var(--ink); }

.field { display: flex; flex-direction: column; gap: .3125rem; }
.field label { font-size: .75rem; font-weight: 600; color: var(--muted); }
.field .hint { font-size: .75rem; color: var(--muted); font-weight: 400; }
.input, .select, textarea.input {
  font: inherit; font-size: .845rem; color: var(--ink);
  padding: .5rem .6875rem; border: 1px solid var(--line); border-radius: 8px; background: #fff;
  width: 100%;
}
.input:focus, .select:focus, textarea.input:focus { border-color: var(--control); outline: none; box-shadow: 0 0 0 3px var(--control-bg); }
.input.mono, textarea.input.mono { font-family: var(--font-mono); font-size: .8125rem; }
.select { appearance: none;
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%235F6E7B' fill='none' stroke-width='1.5'/%3E%3C/svg%3E") no-repeat right .6875rem center; padding-right: 1.75rem; }
.search { position: relative; }
.search .input { padding-left: 2rem; }
/* Escaped, not literal. Stylesheets go out as `text/css` with no charset, so a
   browser that falls back to latin-1 renders a literal glyph here as mojibake
   ("âŒ•" instead of the magnifier). An escape is plain ASCII in the file and
   cannot be decoded wrongly, whatever the server sends. */
.search::before { content: "\2315"; position: absolute; left: .625rem; top: .4375rem; color: var(--muted); font-size: 1rem; }

.switch { width: 2.125rem; height: 1.25rem; border-radius: 999px; background: #C4CED7; position: relative; border: none; flex: none; }
.switch::after { content: ""; position: absolute; top: .125rem; left: .125rem; width: 1rem; height: 1rem;
  border-radius: 50%; background: #fff; transition: left .15s; }
.switch.on { background: var(--clean); }
.switch.on::after { left: 1rem; }

/* row selection */
.check { width: 1rem; height: 1rem; accent-color: var(--control); vertical-align: middle; }
.bulk-bar {
  display: flex; align-items: center; gap: .75rem; margin-bottom: .75rem;
  padding: .625rem 1rem; font-size: .8125rem; font-weight: 600;
  background: var(--control-bg); color: var(--control-deep);
  border: 1px solid var(--control-line); border-radius: var(--radius);
}
.bulk-bar .spacer { flex: 1; }
.bulk-bar[hidden] { display: none; }

/* ---------- panels / tables ---------- */
.panel { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }
.panel .panel-head { display: flex; align-items: center; gap: .625rem; padding: .8125rem 1rem; border-bottom: 1px solid var(--line-soft); }
.panel .panel-head h2 { font-family: var(--font-display); font-size: .9375rem; font-weight: 600; }
.panel .panel-head .spacer { flex: 1; }
.panel .panel-body { padding: 1rem; }

.toolbar { display: flex; gap: .625rem; align-items: center; margin-bottom: .875rem; flex-wrap: wrap; }
.toolbar .spacer { flex: 1; }

.table { width: 100%; border-collapse: collapse; background: var(--panel); }
/* A bordered, scrolling list of rows — users to pick, checker addresses, tags.
   Lived in two page stylesheets and was about to be copied into a third; the
   registry's tag list had the class and none of the rules, so it kept the height
   limit and lost the scrolling, and the rows spilled over the hint below it.
   Height stays with each page: how tall the list should be is the one thing they
   genuinely disagree about. */
.picker { overflow-y: auto; border: 1px solid var(--line); border-radius: var(--radius); background: #fff; }
.picker .pick-row {
  display: flex; align-items: center; gap: .625rem; padding: .4375rem .75rem;
  border-bottom: 1px solid var(--line-soft); font-weight: 400; color: var(--ink);
}
.picker .pick-row:last-child { border-bottom: none; }
.picker .pick-row:hover { background: #F7F9FB; }
/* `display: flex` above beats the attribute on its own, so a row hidden by a
   filter would otherwise stay on screen. */
.picker .pick-row[hidden] { display: none; }

.table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); background: var(--panel); }
.table th {
  text-align: left; font-size: .66rem; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); padding: .625rem .875rem; border-bottom: 1px solid var(--line); white-space: nowrap;
  background: #FAFBFC;
}
.table th.sort { color: var(--ink); }
.table th.sort::after { content: " \2193"; color: var(--control); }
.table td { padding: .625rem .875rem; border-bottom: 1px solid var(--line-soft); font-size: .8125rem; vertical-align: middle; }
.table tr:last-child td { border-bottom: none; }
.table tr:hover td { background: #F7F9FB; }
.table tr.selected td { background: var(--control-bg); }
.domain { font-family: var(--font-mono); font-size: .8125rem; display: inline-flex; align-items: center; gap: .5rem; color: var(--ink); }
.mono { font-family: var(--font-mono); font-size: .78rem; }
.dim { color: var(--muted); }
.num { font-family: var(--font-mono); font-size: .78rem; text-align: right; }
td.actions, th.actions { text-align: right; white-space: nowrap; }
td.pick, th.pick { width: 1px; padding-right: 0; }

/* Opt-in per table, via `frozen-name` on the <table>: a pinned checkbox with the
   name scrolling away from it is worse than nothing, so the two are never
   separable. Every other table in the product keeps its checkbox where it is.
   A wide table scrolls sideways, and the first thing to leave is the only column
   that says which row you are looking at. So the checkbox and the name stay put
   and everything else moves under them.
   Both, not just the name: a tick box you cannot match to a domain is worse than
   no tick box. The pick column gets a fixed width so the name column's offset is
   a number and not a guess about how wide a checkbox renders today. */
/* `min-width`, not `width`: on a table cell `width` is a suggestion the auto
   layout is free to ignore, and it did — the column came out 34px against the
   44px the name column was told to pin at, leaving a 16px slot for the scrolled
   content to show through. A minimum it cannot go under is what makes the two
   numbers agree. */
.table.frozen-name th.pick, .table.frozen-name td.pick { position: sticky; left: 0; z-index: 2; min-width: 2.75rem; }
.table.frozen-name th.sticky-name, .table.frozen-name td.sticky-name { position: sticky; left: 2.75rem; z-index: 2; }
.table.frozen-name td.pick, .table.frozen-name td.sticky-name { background: var(--panel); }
.table.frozen-name th.pick, .table.frozen-name th.sticky-name { background: #FAFBFC; z-index: 3; }
/* The seam where the frozen part ends, drawn as an element rather than a shadow:
   the table is `border-collapse: collapse`, and browsers do not paint box-shadow
   on cells of a collapsed table. Changing the border model of every table in the
   product to buy one shadow is the wrong trade. */
.table.frozen-name th.sticky-name::after, .table.frozen-name td.sticky-name::after {
  content: ""; position: absolute; top: 0; right: -0.5rem; bottom: 0; width: 0.5rem;
  pointer-events: none;
  background: linear-gradient(to right, rgba(16, 24, 40, .10), rgba(16, 24, 40, 0));
}
/* Re-stated after the sticky background, or the row would stop reacting exactly
   where the pointer is. */
.table.frozen-name tr:hover td.pick, .table.frozen-name tr:hover td.sticky-name { background: #F7F9FB; }
.table.frozen-name tr.selected td.pick, .table.frozen-name tr.selected td.sticky-name { background: var(--control-bg); }

.pagination { display: flex; gap: .25rem; align-items: center; margin-top: .875rem; justify-content: flex-end; }
.pagination a { padding: .3125rem .625rem; border: 1px solid var(--line); border-radius: 7px; font-size: .78rem; color: var(--ink); background: #fff; }
.pagination a.cur { background: var(--control); border-color: var(--control); color: #fff; }
.pagination .dots { color: var(--muted); padding: 0 .25rem; }

/* stat tiles */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: .75rem; margin-bottom: 1rem; }
.stat { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: .75rem .875rem; box-shadow: var(--shadow); }
.stat .k { font-size: .6875rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); display: flex; align-items: center; gap: .4375rem; }
.stat .v { font-family: var(--font-display); font-size: 1.5rem; font-weight: 600; margin-top: .25rem; letter-spacing: -.02em; }
.stat .d { font-size: .75rem; color: var(--muted); margin-top: .125rem; }
.stat.fire .v { color: var(--ember-deep); }

/* key-value */
.kv { display: grid; grid-template-columns: 9.375rem 1fr; row-gap: .5625rem; column-gap: .875rem; font-size: .8125rem; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; }

/* ---------- modal ----------
   The shell is a column: head and foot hold their size, the body scrolls. A tall
   pop-up used to grow past the viewport and take its own close button with it. */
.overlay {
  position: fixed; inset: 0; background: rgba(16,27,38,.44); backdrop-filter: blur(1.5px);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 2.5rem 1rem; z-index: 40; overflow-y: auto;
}
.modal {
  background: #fff; border-radius: 14px; width: 35rem; max-width: 100%;
  box-shadow: 0 24px 64px rgba(16,27,38,.28);
  display: flex; flex-direction: column; max-height: calc(100vh - 5rem);
}
.modal[hidden] { display: none; }
/* a form wrapping body+foot has to pass the column layout through, or the body
   stops scrolling and the pop-up grows past the viewport again */
.modal > form { display: flex; flex-direction: column; min-height: 0; }
.modal .m-head { display: flex; align-items: center; flex-wrap: wrap; gap: .5rem; padding: 1rem 1.25rem; border-bottom: 1px solid var(--line-soft); flex: none; }
.modal .m-head h2 { font-family: var(--font-display); font-size: 1rem; font-weight: 600; }
.modal .m-head .x { margin-left: auto; }
.modal .m-body { padding: 1.125rem 1.25rem; display: flex; flex-direction: column; gap: .875rem; overflow-y: auto; min-height: 0; }
.modal .m-foot { display: flex; justify-content: flex-end; gap: .625rem; padding: .875rem 1.25rem; border-top: 1px solid var(--line-soft); background: #FAFBFC; border-radius: 0 0 14px 14px; flex: none; }

/* tab strip inside a pop-up */
.tabs { display: flex; gap: .125rem; padding: 0 1.25rem; border-bottom: 1px solid var(--line-soft); flex: none; overflow-x: auto; }
.tabs button {
  border: none; background: none; white-space: nowrap;
  padding: .625rem .75rem; font-size: .8125rem; font-weight: 600; color: var(--muted);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tabs button:hover { color: var(--ink); }
.tabs button.on { color: var(--ink); border-bottom-color: var(--control); }
.tabs button .n { font-family: var(--font-mono); font-size: .6875rem; color: var(--muted); margin-left: .375rem; }
.tab-pane[hidden] { display: none; }

/* form layout utilities (were repeated as inline styles across the pop-ups) */
.form-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: .875rem; }
.form-grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: .875rem; }
.switch-line { display: flex; align-items: center; gap: .5rem; padding-top: .25rem; font-size: .8125rem; }
.check-line { display: flex; gap: 1.125rem; padding-top: .125rem; font-size: .8125rem; }
.check-line label { display: flex; gap: .4375rem; align-items: center; font-weight: 400; color: var(--ink); }
@media (max-width: 700px) { .form-grid-2, .form-grid-3 { grid-template-columns: 1fr; } }

/* access list rows — the shared "who else can see this" panel, used by every
   object that can be shared. It lived in the one-step feature CSS, so the same
   partial rendered unstyled on the flows page. */
.share-row {
  display: flex; align-items: center; gap: .625rem;
  padding: .5625rem 1rem; font-size: .8125rem;
  border-bottom: 1px solid var(--line-soft);
}
.share-row:last-child { border-bottom: none; }
.share-row .spacer { flex: 1; }
@media (max-width: 700px) { .share-row { flex-wrap: wrap; } }

/* warn block (cross-flow confirmation) */
.note { border-radius: 9px; padding: .6875rem .8125rem; font-size: .8125rem; display: flex; gap: .625rem; align-items: flex-start; }
.note.warn { background: var(--amber-bg); color: #6E4C0C; }
.note.fire { background: var(--ember-bg); color: var(--ember-deep); }
.note.info { background: var(--control-bg); color: var(--control-deep); }
.note .flare { margin-top: .25rem; }

/* ---------- steps (flow editor) ---------- */
.steps { display: flex; flex-direction: column; }
.step-card { position: relative; padding-left: 2.125rem; padding-bottom: 1.375rem; }
.step-card::before {
  content: ""; position: absolute; left: .6875rem; top: 1.875rem; bottom: 0; width: 2px; background: var(--line);
}
.step-card:last-child::before { display: none; }
.step-card .step-no {
  position: absolute; left: 0; top: .25rem; width: 1.5rem; height: 1.5rem; border-radius: 7px;
  background: var(--ink); color: #fff; font-family: var(--font-mono); font-size: .75rem;
  display: flex; align-items: center; justify-content: center; transform: rotate(45deg);
}
.step-card .step-no span { transform: rotate(-45deg); }
.pool { display: flex; flex-wrap: wrap; gap: .5rem; }
.pool .pd {
  display: inline-flex; align-items: center; gap: .5rem; font-family: var(--font-mono); font-size: .78rem;
  border: 1px solid var(--line); border-radius: 8px; padding: .3125rem .625rem; background: #fff;
}
.pool .pd.off { opacity: .55; border-style: dashed; }
.pool .pd .x { color: var(--muted); font-size: .75rem; }

/* progress */
.progress { height: .5rem; border-radius: 4px; background: var(--neutral-bg); overflow: hidden; }
.progress i { display: block; height: 100%; background: var(--control); }

/* login */
.login-wrap { min-height: 100vh; display: flex; align-items: center; justify-content: center; background: var(--mist); position: relative; overflow: hidden; }
.login-wrap::before {
  content: ""; position: absolute; inset: -40% 45% 55% -10%;
  background: linear-gradient(135deg, rgba(41,70,216,.10), rgba(41,70,216,0));
  transform: rotate(-8deg);
}
.login-card { width: 23.75rem; background: #fff; border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow); padding: 1.875rem 1.75rem; position: relative; }
.login-card .wordmark { border: none; padding: 0 0 .375rem; margin: 0 0 .125rem; color: var(--ink); font-size: 1.3125rem; }
.login-card .tag { color: var(--muted); font-size: .8125rem; margin-bottom: 1.375rem; }
.login-card form { display: flex; flex-direction: column; gap: .875rem; }

/* empty state */
.empty { text-align: center; padding: 2.875rem 1.25rem; color: var(--muted); }
.empty .flare { width: .75rem; height: .75rem; margin-bottom: .625rem; }
.empty h3 { font-family: var(--font-display); font-size: .9375rem; color: var(--ink); margin-bottom: .25rem; }

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

/* ---------- mobile ---------- */
@media (max-width: 700px) {
  :root { --ui-base: 17px; }
  .app { grid-template-columns: 1fr; }
  .rail { display: none; }
  .rail.open {
    display: flex; position: fixed; inset: 0 auto 0 0; width: 15rem; z-index: 60;
    box-shadow: 0 0 0 100vmax rgba(16,27,38,.44);
  }
  .burger { display: flex; align-items: center; justify-content: center; }
  .topbar { padding: .75rem .875rem; gap: .625rem; }
  .content { padding: 1rem .875rem 2.5rem; }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .kv { grid-template-columns: 1fr; row-gap: .125rem; }
  .kv dt { margin-top: .5rem; }
  .user .who { display: none; }
  .modal { width: 100%; max-height: calc(100vh - 3rem); }
  .overlay { padding: 1.5rem .625rem; }

  /* tables collapse to cards */
  .table-wrap { border: none; box-shadow: none; background: none; overflow: visible; }
  .table, .table tbody, .table tr, .table td { display: block; width: 100%; }
  .table thead { display: none; }
  .table tr {
    background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
    box-shadow: var(--shadow); margin-bottom: .625rem; padding: .375rem .125rem;
  }
  .table td { border: none; padding: .4375rem .875rem; }
  .table td[data-l]::before {
    content: attr(data-l); display: block; font-size: .66rem; font-weight: 600;
    letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin-bottom: .125rem;
  }
  td.actions { text-align: left; }
  td.pick, th.pick { width: auto; }
  /* Nothing to freeze once the row is a card — and a sticky block-level cell
     would sit on top of the card it belongs to. */
  .table.frozen-name td.pick, .table.frozen-name td.sticky-name,
  .table.frozen-name th.pick, .table.frozen-name th.sticky-name {
    position: static; background: none;
  }
  .table.frozen-name th.sticky-name::after, .table.frozen-name td.sticky-name::after { display: none; }
}

/* ---------- app-runtime additions (not in mockups) ---------- */

/* Loader overlay (loader.js) */
#loader {
  position: fixed; inset: 0; z-index: 90; display: flex;
  align-items: center; justify-content: center;
  background: rgba(16,27,38,.30); backdrop-filter: blur(1px);
}
#loader .loader-img { width: 3.5rem; height: 3.5rem; }

/* Toasts (helper.alert.toast) — bottom right, newest at the bottom, out of the
   way of the page head and the primary action in the top-right corner. */
#alert-container {
  position: fixed; bottom: 1.25rem; right: 1.25rem; z-index: 95;
  display: flex; flex-direction: column; gap: .5rem; align-items: flex-end;
  pointer-events: none;
}
.toast {
  pointer-events: auto; cursor: default;
  display: flex; align-items: flex-start; gap: .5rem;
  border-radius: 10px; padding: .625rem .875rem .625rem .75rem;
  font-size: .8125rem; line-height: 1.4; color: var(--ink);
  background: var(--panel); border: 1px solid var(--line);
  border-left: 3px solid var(--control);
  box-shadow: 0 2px 6px rgba(16,27,38,.08), 0 12px 28px rgba(16,27,38,.12);
  max-width: 24rem;
  animation: toast-in .18s ease-out;
}
.toast.leaving { animation: toast-out .18s ease-in forwards; }
.toast::before {
  content: ""; width: .5rem; height: .5rem; border-radius: 2px; flex: none;
  margin-top: .3125rem; transform: rotate(45deg); background: var(--control);
}
.toast a { text-decoration: underline; }
.toast-success { border-left-color: var(--clean); }
.toast-success::before { background: var(--clean); }
.toast-warning { border-left-color: var(--amber); }
.toast-warning::before { background: var(--amber); }
.toast-error { border-left-color: var(--ember); }
.toast-error::before { background: var(--ember); }

@keyframes toast-in  { from { opacity: 0; transform: translateY(.5rem); } }
@keyframes toast-out { to   { opacity: 0; transform: translateX(.75rem); } }

@media (max-width: 700px) {
  #alert-container { left: .75rem; right: .75rem; bottom: .75rem; align-items: stretch; }
  .toast { max-width: none; }
}

/* Shared pop-up shell (server-rendered modal content injected here) */
#pop-up { display: none; }
#pop-up.open { display: flex; }

/* Validation errors block */
#validation-errors { display: none; }
#validation-errors.show {
  display: block; margin-bottom: .875rem; border-radius: 9px;
  background: var(--ember-bg); color: var(--ember-deep); padding: .6875rem .875rem; font-size: .8125rem;
}

/* ---------- SweetAlert2 theme (alerts.js applies the classes) ---------- */
.ops-swal { z-index: 100; }
.ops-swal-popup {
  width: 27rem; max-width: calc(100vw - 2rem); padding: 1.5rem 1.5rem 1.25rem;
  border-radius: 14px; background: var(--panel); font-family: var(--font-ui);
  box-shadow: 0 24px 64px rgba(16,27,38,.28);
}
.ops-swal-title {
  font-family: var(--font-display); font-size: 1.0625rem; font-weight: 600;
  color: var(--ink); padding: 0; line-height: 1.3;
}
.ops-swal-text { font-size: .845rem; color: var(--muted); margin: .5rem 0 0; text-align: left; }
.ops-swal-text ul { margin: .5rem 0 0 1rem; }
.ops-swal-actions { gap: .625rem; margin: 1.25rem 0 0; }
/* An option inside a confirmation, not decoration around it: boxed and set apart
   so it reads as a decision the dialog is asking for. */
.swal-check {
  display: flex; align-items: center; gap: .5rem; margin: .875rem 0 0;
  padding: .625rem .75rem; border: 1px solid var(--line); border-radius: 9px;
  background: var(--mist); font-size: .845rem; color: var(--ink);
  text-align: left; cursor: pointer;
}
.swal-check input { width: .9375rem; height: .9375rem; accent-color: var(--control); cursor: pointer; }
.swal-check-hint { margin: .375rem .125rem 0; font-size: .78rem; color: var(--muted); text-align: left; }
.ops-swal-invalid { background: var(--ember-bg); color: var(--ember-deep); border-radius: 8px; font-size: .78rem; }
.ops-swal-popup .swal2-close { color: var(--muted); font-size: 1.5rem; }
/* Resize the icon through font-size, never width/height: SweetAlert builds the
   success tick and the error cross out of em-positioned lines inside a 5em box,
   so a box shrunk in rem leaves those lines at their old length — the tick comes
   out as a slash. font-size scales the box and its contents together. */
.ops-swal-popup .swal2-icon { font-size: .72rem; margin: 0 auto .875rem; }
.ops-swal-popup .swal2-success { border-color: var(--clean); color: var(--clean); }
.ops-swal-popup .swal2-success [class^='swal2-success-line'] { background-color: var(--clean); }
.ops-swal-popup .swal2-success .swal2-success-ring { border-color: rgba(24,138,84,.28); }
.ops-swal-popup .swal2-error { border-color: var(--ember); color: var(--ember); }
.ops-swal-popup .swal2-error [class^='swal2-x-mark-line'] { background-color: var(--ember); }
.ops-swal-popup .swal2-warning { border-color: var(--amber); color: var(--amber); }
.ops-swal-popup .swal2-info,
.ops-swal-popup .swal2-question { border-color: var(--control); color: var(--control); }
