/* ===========================================================================
   gensys-mail admin panel — visual identity derived from gensys.pl
   Palette (from gensys.pl/css/layout.css):
     --tan     #b6a88b   primary accent (buttons, active state) — white text
     --taupe   #6f6755   headings, nav, links
     --taupe-d #453f45   deepest heading ink
     --ink     #383838   primary body heading
     --body    #4e4e4e   body text
     --meta    #686868   secondary/meta text
     --line    #eeece7   hairline dividers (warm)
     --sand    #e7e2d6   warm panel tint
     --bg      #faf9f7   page background (warm off-white)
   Type: Arial / Tahoma, sans-serif (as the main site). 5px radius is the
   house rounding. Restraint over decoration — this is an operator tool.
   =========================================================================== */

:root {
  --tan: #b6a88b;
  --tan-dark: #9c8e72;
  --taupe: #6f6755;
  --taupe-deep: #453f45;
  --ink: #383838;
  --body: #4e4e4e;
  --meta: #686868;
  --line: #eeece7;
  /* --edge: the OUTER boundary of a container (card, table, bubble).
     --line (#eeece7) measures 1.12:1 against the page — technically a border,
     visually a rumour, which is why the operator asked for boundaries on the
     tables and bubbles. --line is right for INTERNAL hairlines (row
     separators) where near-invisibility is the point; it was never a container
     edge. --edge is ~1.9:1: findable without shouting. Full --tan (2.23:1) on
     every table would read as decoration. */
  --edge: #c4b89c;
  --sand: #e7e2d6;
  --bg: #faf9f7;
  --white: #ffffff;
  --danger: #9b4a3f;
  --radius: 5px;
  --shadow: 0 1px 3px rgba(69, 63, 69, 0.10);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--body);
  font-family: Arial, Tahoma, Geneva, sans-serif;
  font-size: 14px;
  line-height: 1.5;
}

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

h1, h2, h3 { color: var(--ink); font-weight: normal; margin: 0 0 0.5em; }
h1 { font-size: 22px; color: var(--taupe); }
h2 { font-size: 16px; }

/* ---- buttons (the gensys.pl tan button, scaled up for an admin form) ---- */
.btn {
  display: inline-block;
  background: var(--tan);
  color: var(--white);
  border: none;
  border-radius: var(--radius);
  padding: 9px 18px;
  font-size: 14px;
  font-weight: bold;
  font-family: inherit;
  cursor: pointer;
  text-align: center;
}
.btn:hover { background: var(--tan-dark); text-decoration: none; }
.btn-block { display: block; width: 100%; }
.btn-quiet {
  background: transparent;
  color: var(--taupe);
  font-weight: normal;
  padding: 6px 10px;
}
.btn-quiet:hover { background: var(--line); }

/* ---- forms ---- */
label { display: block; color: var(--taupe); font-size: 13px; margin-bottom: 4px; }
/* Form controls. textarea BELONGS IN THIS LIST — it was missing, so it had no
   border of its own and only picked one up where a context rule happened to add
   it (.confirm-body textarea, with --line at 1.12:1: invisible). An input and a
   textarea are the same kind of thing to the person typing in them; styling one
   and not the other is how a field ends up borderless. */
input[type=text], input[type=password], input[type=email], input[type=number],
textarea, select {
  width: 100%;
  padding: 9px 10px;
  border: 1px solid var(--sand);
  border-radius: var(--radius);
  font-family: inherit;
  font-size: 14px;
  color: var(--ink);
  background: var(--white);
  box-sizing: border-box;
}
textarea { resize: vertical; min-height: 68px; line-height: 1.5; }
/* select is a control, not a block: it should size to its content, and a native
   dropdown must keep its own arrow affordance. */
select { width: auto; padding: 7px 10px; }
input:focus, textarea:focus, select:focus {
  outline: none;
  border-color: var(--tan);
  box-shadow: 0 0 0 2px rgba(182, 168, 139, 0.25);
}
.field { margin-bottom: 16px; }

/* ---- centred auth card (login / totp) ---- */
.auth-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.auth-card {
  width: 100%;
  max-width: 360px;
  background: var(--white);
  border: 1px solid var(--line);
  border-top: 3px solid var(--tan);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 28px 28px 32px;
}
.brand {
  text-align: center;
  margin-bottom: 22px;
}
.brand .mark {
  font-size: 20px;
  letter-spacing: 3px;
  color: var(--taupe);
  font-weight: bold;
}
.brand .sub {
  font-size: 11px;
  color: var(--meta);
  letter-spacing: 1px;
  text-transform: uppercase;
  margin-top: 2px;
}
.alert {
  background: #f6ede9;
  border: 1px solid #e3c7bf;
  color: var(--danger);
  border-radius: var(--radius);
  padding: 9px 12px;
  font-size: 13px;
  margin-bottom: 16px;
}
.hint { color: var(--meta); font-size: 12px; margin-top: 14px; text-align: center; }

/* ---- app shell (authenticated) ---- */
.topbar {
  background: var(--white);
  border-bottom: 1px solid var(--line);
  border-top: 3px solid var(--tan);
  padding: 0 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 56px;
}
.topbar .mark { font-size: 16px; letter-spacing: 2px; color: var(--taupe); font-weight: bold; }
.topbar .who { color: var(--meta); font-size: 13px; }
.topbar .who strong { color: var(--ink); font-weight: normal; }
.topbar form { display: inline; margin-left: 14px; }

.container { max-width: 980px; margin: 28px auto; padding: 0 24px; }

.card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 22px 24px;
  margin-bottom: 20px;
}

.role-badge {
  display: inline-block;
  background: var(--sand);
  color: var(--taupe);
  border-radius: var(--radius);
  font-size: 11px;
  padding: 2px 8px;
  letter-spacing: 0.5px;
}

.muted { color: var(--meta); }

/* accessibility: visible focus everywhere */
a:focus-visible, .btn:focus-visible, input:focus-visible {
  outline: 2px solid var(--taupe);
  outline-offset: 1px;
}

@media (max-width: 520px) {
  .container { margin: 16px auto; }
  .topbar { padding: 0 14px; }
}

/* ===========================================================================
   Admin-management screens — same earth-tone system, extended.
   =========================================================================== */

/* top nav (operator links) */
.topnav { flex: 1; margin-left: 28px; }
.topnav a {
  color: var(--taupe);
  font-size: 14px;
  padding: 6px 2px;
  border-bottom: 2px solid transparent;
}
.topnav a:hover { text-decoration: none; border-bottom-color: var(--tan); }

/* page header with an action on the right */
.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
.page-head h1 { margin: 0; }

.back { color: var(--meta); font-size: 13px; }
.back:hover { color: var(--taupe); }

/* data table
   Row density (2026-07-02): tightened from 11px/8px vertical padding so more
   rows fit above the fold on mailbox-heavy domains, while keeping enough
   breathing room for the two-line usage/outbound cells (number + bar). */
/* Data tables get an OUTER boundary. Internal row separators stay --line: the
   eye needs the table's extent, not a grid. border-collapse means the outer
   border must go on the table itself; the radius needs overflow:hidden to clip
   the corner cells. */
table.data {
  width: 100%; border-collapse: collapse; font-size: 14px;
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--white);
}
table.data thead th { background: #f7f5f0; }
table.data th {
  text-align: left;
  color: var(--meta);
  font-weight: normal;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  padding: 0 10px 6px;
  border-bottom: 1px solid var(--line);
}
table.data td {
  padding: 4px 10px;
  border-bottom: 1px solid var(--line);
  color: var(--body);
}
/* nowrap utility: short two-word cell values ("3h ago", "just now",
   "(dot) active") must never wrap into a second line — content wrapping,
   not padding, was inflating rows after the 2026-07-02 density pass.
   fmtWhen() emits it on its span; status cells carry it on the td. */
.nw { white-space: nowrap; }
table.data tr:last-child td { border-bottom: none; }
/* the header rule is the table's own top hairline; keep it quiet inside a
   bordered container */
table.data th { border-bottom-color: var(--edge); }
table.data tbody tr:hover { background: #fbfaf8; }

/* role badge variants */
.role-super { background: var(--taupe); color: #fff; }

/* status dot. Also reused as the domain-list Spam RAG icon (2026-07-02):
   dot-on = green/clean, dot-off = amber/anomaly, dot-crit = red/spoofing.
   In the RAG cell the amber/red dot is an <a> deep-linking to the signal's
   card; the title attribute carries the reason(s). */
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; vertical-align: middle; margin-right: 4px; }
.dot-on   { background: #6f8f5b; }   /* muted sage green, fits the earth palette */
.dot-off  { background: #c9a23f; }   /* muted amber */
.dot-warn { background: #b06a5a; }   /* muted terracotta: generic suppressed */
.dot-crit { background: var(--danger); }

/* ---------------------------------------------------------------------------
   Suppression reasons — one colour per REASON, not one for "suppressed".
   The three are different facts and call for different operator action, so a
   single terracotta dot for all of them (what .dot-warn used to do everywhere)
   hid the distinction that matters:

     bounced       the ADDRESS is dead. Written ONLY on a hard 5.x.x DSN
                   (gensys-newsletter-bounce gates the suppression insert on
                   `if hard:` — a soft 4.x.x marks the delivery bounced but
                   never suppresses). Nothing to do; the mailbox is gone.
                   Deep blue: a fact about the world, not a verdict on us.
     unsubscribed  the PERSON chose to leave. Correct, healthy, expected —
                   this is the system working. Amber (the hue .dot-off already
                   uses for "intentionally not receiving"), NOT red: colouring a
                   lawful opt-out as an error trains the operator to read
                   consent as damage.
     complaint     the person hit "spam". The only WARNING here: a reputation
                   event, and repeated ones cost deliverability for every tenant
                   on the shared IP. Deep red — the only red, so it stands out
                   instead of blending into a wall of equally-alarming dots.

   COLOUR CHOICE IS MEASURED, NOT TASTE. Every value below was checked against
   THREE constraints at once, because satisfying any two is easy and useless:
     1. deuteranopia + protanopia simulation (~8% of men have some CVD)
     2. greyscale luminance separation (printing, e-ink, screenshots)
     3. contrast >= 3:1 against the page (an 8px dot must be VISIBLE)
   The process failed twice before it passed, which is why the numbers are
   recorded rather than the intent:
     - slate #7d8791 vs sage: deutan distance 37, and luminance 0.237 vs 0.238 —
       literally the same dot in greyscale.
     - --danger #9b4a3f vs sage: 41 deutan / 39 protan — the textbook red/green
       collision, already latent in the palette before this change.
     - pale slate #a4c8cc separated well from every other dot but sat at 1.70:1
       on the page — invisible. Optimising dot-vs-dot while ignoring dot-vs-page
       produced a set that was beautifully distinguishable and unreadable.
   The binding pair turned out to be sage-vs-amber under deutan: deutan collapses
   green toward yellow, and darkening amber for contrast pushes it TOWARD sage's
   luminance. Resolved by moving amber to a burnt orange (#b76008) that clears
   sage on hue AND luminance while gaining contrast.
   Final: worst pairwise CVD distance 68 (>=60), min luminance gap 0.053
   (>=0.04), min page contrast 3.47:1 (>=3.0).

   Colour is still the SECONDARY channel by design: every dot carries its status
   as TEXT beside it, and the legend is always rendered. A colour-only signal is
   one that lies to some of its readers.

   Hollow ring variant (.dot-scope-list) marks a LIST-scoped suppression vs a
   domain-wide one — see the legend in the newsletter template.
   --------------------------------------------------------------------------- */
.dot-bounced      { background: #3f5f7d; }   /* deep blue   6.35:1  L=.107  dead address */
.dot-unsubscribed { background: #b76008; }   /* burnt amber 4.26:1  L=.185  chose to leave */
.dot-complaint    { background: #7a1414; }   /* deep red   10.30:1  L=.047  reputation event */

/* A list-scoped suppression is drawn hollow: same colour (same reason), open
   centre (narrower scope). Domain-wide stays solid. This keeps the colour axis
   meaning REASON and the fill axis meaning SCOPE, so the two never compete —
   an operator reads "why" from hue and "how far" from fill. */
.dot-scope-list {
  background: transparent;
  box-shadow: inset 0 0 0 2px currentColor;
}
.dot-scope-list.dot-bounced      { color: #3f5f7d; }
.dot-scope-list.dot-unsubscribed { color: #b76008; }
.dot-scope-list.dot-complaint    { color: #7a1414; }

/* Legend: sits under the member table, explains the dots without a tooltip
   (tooltips are invisible on touch and unprintable). Small, quiet, always
   present — a legend that only appears when something is wrong is a legend
   nobody has learned to read by the time it matters. */
.nl-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  margin: 12px 0 0;
  padding: 10px 12px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: 12px;
  color: var(--meta);
}
.nl-legend-item { display: inline-flex; align-items: center; gap: 6px; }
.nl-legend-item .dot { margin-right: 0; }
.nl-legend-note { flex-basis: 100%; margin: 2px 0 0; color: var(--meta); font-size: 11.5px; }

/* alerts */
.alert-ok    { background: #eef1e9; border: 1px solid #cdd6bd; color: #4a5a36; }
.alert-error { background: #f6ede9; border: 1px solid #e3c7bf; color: var(--danger); }
.alert-info  { background: #f0efe9; border: 1px solid var(--sand); color: var(--taupe); }
/* warn: launched-but-parked and similar 'succeeded, but act on this' notices */
.alert-warn  { background: #fbf3e2; border: 1px solid #e6cf9a; color: #7a5a1e; }
/* inline 'paused' badge on a sending mailing whose domain has sending disabled */
.nl-paused { display: inline-block; margin-left: 6px; padding: 0 6px; font-size: 11px;
  font-weight: bold; text-transform: uppercase; letter-spacing: 0.04em;
  background: #fbf3e2; border: 1px solid #e6cf9a; color: #7a5a1e; border-radius: var(--radius); }
/* dedicated sending on/off toggle row in the Settings tab */
.nl-toggle-row { display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; padding: 14px 16px; margin: 4px 0 20px;
  background: var(--sand); border: 1px solid var(--line); border-radius: var(--radius); }
.nl-on  { font-weight: bold; color: #4a5a36; }   /* sending ON  — green ink  */
.nl-off { font-weight: bold; color: #7a5a1e; }   /* sending OFF — amber ink  */
.nl-subhead { margin: 0 0 6px; font-size: 14px; color: var(--taupe); }

/* ---- mailing detail page ---- */
.nl-detail-meta, .nl-detail-progress, .nl-detail-body, .nl-detail-times { margin-bottom: 16px; }
.kv { display: flex; gap: 12px; padding: 4px 0; }
.kv .k { flex: 0 0 150px; color: var(--taupe); font-size: 13px; }
.kv .v { flex: 1; }
.nl-stat-row { display: flex; flex-wrap: wrap; gap: 18px; margin-bottom: 10px; }
.nl-stat { font-size: 14px; }
.nl-stat strong { font-size: 18px; }
/* sandboxed HTML preview: framed, white, no chrome; height is generous but bounded */
.nl-html-preview { width: 100%; height: 420px; border: 1px solid var(--sand);
  border-radius: var(--radius); background: #fff; }
.nl-text-preview { white-space: pre-wrap; word-break: break-word; background: var(--white);
  border: 1px solid var(--sand); border-radius: var(--radius); padding: 12px; margin: 0;
  font-family: var(--mono, monospace); font-size: 13px; max-height: 300px; overflow: auto; }
.nl-detail-actions { display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap;
  margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--line); }
.link-quiet { color: var(--taupe); text-decoration: none; font-size: 14px; }
.link-quiet:hover { text-decoration: underline; }

/* ---- inline mailing editor (draft detail) ---- */
.nl-edit-clickable { cursor: pointer; border-bottom: 1px dashed var(--sand); }
.nl-edit-clickable:hover { background: var(--sand); }
.nl-edit-active { display: inline-flex; gap: 6px; align-items: center; }
.nl-edit-input { padding: 3px 6px; border: 1px solid var(--taupe); border-radius: var(--radius);
  font-size: 14px; min-width: 220px; }
.btn-sm { padding: 3px 10px; font-size: 13px; border: 1px solid var(--taupe);
  background: var(--white); border-radius: var(--radius); cursor: pointer; }
.nl-edit-msg { font-size: 12px; color: var(--taupe); }
.nl-edit-msg.nl-edit-err { color: var(--danger); }
.nl-edit-msg.nl-edit-ok  { color: #4a5a36; }
.nl-edit-hint { margin-top: 12px; font-size: 13px; }
.nl-bulk-edit { margin-bottom: 16px; }
.nl-edit-actions { display: flex; align-items: center; gap: 12px; margin-top: 8px; }

/* warn / danger cards */
.card-warn   { border-left: 3px solid var(--tan); }
.card-danger { border-left: 3px solid var(--danger); }

/* button variants */
.btn-warn   { background: var(--taupe); }
.btn-warn:hover { background: var(--taupe-deep); }
.btn-danger { background: var(--danger); }
.btn-danger:hover { background: #7e3a31; }

/* inline form spacing within control cards */
.inline-form { display: inline-block; margin: 6px 8px 6px 0; }

/* Newsletter single-subscriber add: lay email + tier + Add out on ONE row.
   The global `input[type=email]{width:100%}` rule would otherwise push the tier
   select and Add button onto a second line (a tall stack), so scope a flex row
   here and give the email field a flexible-but-capped width. Wraps gracefully on
   very narrow viewports rather than overflowing. */
.nl-add-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 6px 0 0;
}
.nl-add-row input[type=email] {
  flex: 1 1 260px;      /* grow to fill, but start ~260px; overrides width:100% */
  min-width: 200px; max-width: 360px; width: auto;
}
.nl-add-row select { flex: 0 0 auto; }
.nl-add-row .btn   { flex: 0 0 auto; }

/* confirm disclosure (typed-name confirmation) */
.confirm { margin: 10px 0; }
.confirm > summary {
  display: inline-block;
  list-style: none;
  cursor: pointer;
}
.confirm > summary::-webkit-details-marker { display: none; }
.confirm-body {
  margin-top: 12px;
  padding: 14px 16px;
  /* white, not #fbfaf8: the old tint was 1.01:1 against the page — the same
     colour to the eye. The bubble now separates by SURFACE as well as border. */
  background: var(--white);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  max-width: 460px;
}
.confirm-body p { margin-top: 0; font-size: 13px; color: var(--body); }
.confirm-body input[type=text] { margin-bottom: 10px; }

/* checklist (domain assignment, super checkbox) */
.checklist { display: flex; flex-wrap: wrap; gap: 8px 18px; margin: 10px 0 16px; }
.check { display: flex; align-items: center; gap: 7px; color: var(--body); font-size: 14px; }
.check input { width: auto; }

/* ===========================================================================
   Operator landing page — summary figures, health, action buttons.
   =========================================================================== */
.stat-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin-bottom: 20px; }
.stat { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); padding: 18px 20px; }
.stat-num { font-size: 34px; color: var(--taupe); line-height: 1; }
.stat-label { font-size: 12px; color: var(--meta); text-transform: uppercase; letter-spacing: 0.5px; margin-top: 6px; }
.stat-wide .stat-label { margin-top: 0; margin-bottom: 8px; }
.stat-line { font-size: 15px; color: var(--ink); }
.stat-sub { font-size: 12px; color: var(--meta); margin-top: 3px; }
.chip { display: inline-block; background: var(--sand); color: var(--taupe); font-size: 11px; padding: 1px 7px; border-radius: var(--radius); margin-left: 6px; }
/* Domain-access chips editor (admin detail): assigned domains as removable
   chips + a datalist-backed "add" input (native searchable dropdown, no JS). */
.chiplist { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 14px; }
.chip-lg { display: inline-flex; align-items: center; gap: 6px; font-size: 13px;
           padding: 4px 6px 4px 10px; margin-left: 0; }
.chip-remove { display: inline; margin: 0; }
.chip-x { background: none; border: none; cursor: pointer; color: var(--taupe);
          font-size: 15px; line-height: 1; padding: 0 3px; border-radius: 3px; }
.chip-x:hover { color: #fff; background: var(--warn, #b4544a); }
/* DMARC warn chips on the domain list (spoofing? / volume spike). */
.chip-warn { background: #b4544a; color: #fff; text-decoration: none; }
.chip-warn:hover { background: #933f37; color: #fff; }
.data-compact td, .data-compact th { padding: 4px 10px; }
.dmarc-stats { margin: 8px 0 10px; }
.add-domain { display: flex; gap: 8px; align-items: center; }
.add-domain input[type="text"] { max-width: 320px; }

.health-head { display: flex; align-items: center; gap: 9px; }
.health-head h2 { margin: 0; font-size: 15px; }
.health-dot { width: 11px; height: 11px; border-radius: 50%; }
.health-ok { border-left: 3px solid #6f8f5b; }
.health-bad { border-left: 3px solid var(--danger); }
.svc-row { display: flex; flex-wrap: wrap; gap: 10px 22px; margin-top: 14px; }
.svc { font-size: 13px; color: var(--body); }
.svc-state { color: var(--meta); margin-left: 3px; }

.action-row { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin-top: 20px; }
.action-btn { display: block; background: var(--white); border: 1px solid var(--line); border-top: 3px solid var(--tan); border-radius: var(--radius); box-shadow: var(--shadow); padding: 18px 20px; text-decoration: none; }
.action-btn:hover { border-top-color: var(--taupe); text-decoration: none; background: #fdfcfa; }
.action-title { display: block; font-size: 16px; color: var(--taupe); font-weight: bold; }
.action-sub { display: block; font-size: 12px; color: var(--meta); margin-top: 4px; }

@media (max-width: 620px) { .stat-grid, .action-row { grid-template-columns: 1fr; } }

/* ===========================================================================
   Domains management — limits, drill-in tables, inline edit/add.
   =========================================================================== */
.field-row { display: flex; gap: 16px; flex-wrap: wrap; }
.field-row .field { flex: 1; min-width: 140px; }
.hint { display: block; font-size: 11px; color: var(--meta); margin-top: 3px; }

/* row action cells (Edit / Delete disclosures side by side) */
.row-actions { white-space: nowrap; }
/* inline row-action FORMS (Reset link, Restore): forms are block by default,
   which stacked the Reset-link button on its own line above Edit/Delete and
   inflated every mailbox row (2026-07-02 density pass). */
form.inline { display: inline-block; margin: 0 2px 0 0; vertical-align: middle; }
/* uniform compact height for ALL quiet buttons in a row-actions cell — the
   Reset-link <button> kept the default 6px padding and towered over the
   3px Edit/Delete summaries, setting the row height. */
.row-actions .btn-quiet { padding: 3px 8px; font-size: 13px; }
/* The actions column must not claim the leftover width. Without this the
   auto-layout hands it whatever the other columns don't use, leaving a dead gap
   to the right of Remove — the operator called it out. width:1% + nowrap is the
   standard shrink-to-fit idiom for a table cell: the browser gives it the
   minimum its content needs and the address column absorbs the rest. */
td.row-actions { width: 1%; white-space: nowrap; text-align: right; }
.confirm.inline { display: inline-block; margin: 0 2px; }
.confirm.inline > summary { padding: 3px 8px; font-size: 13px; }
.btn-quiet-danger { color: var(--danger); }
/* Inside a bubble the type is a notch smaller; the box itself comes from the
   base control rule above — this used to re-declare the whole box AND override
   the border to --line (invisible). A context rule should say what DIFFERS. */
.confirm-body textarea { font-size: 13px; padding: 8px 10px; }
/* a wider confirm body for the inline edit forms */
.row-actions .confirm-body { min-width: 280px; }

/* ===========================================================================
   Tabbed mailboxes / aliases (CSS :target, no JS). Default = mailboxes.
   =========================================================================== */
.card.tabs { padding-top: 0; }

.tabbar {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--line);
  margin: 0 -20px 18px;   /* bleed to the card edges */
  padding: 0 20px;
}
.tab {
  padding: 14px 16px;
  color: var(--meta);
  font-size: 14px;
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.tab:hover { color: var(--taupe); text-decoration: none; }

/* A navigation tab that LINKS to another page (e.g. the per-domain newsletter
   workspace) rather than switching an in-page :target panel. Pushed to the far
   right and given a subtle arrow so it reads as "go here", not "show panel". */
.tab-link { margin-left: auto; }
.tab-link .tab-link-arrow { opacity: .55; font-size: 12px; }
.tab-link:hover .tab-link-arrow { opacity: 1; }

/* panel header: title left, Add control right */
.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}
.panel-head h2 { margin: 0; }
.add-inline { margin: 0; }
.add-inline > summary { padding: 7px 14px; }

/* An OPEN disclosure hides its own trigger.
   The operator: "i see add addresses button when clicked dissapears the pane -
   it should not be like that - remove it when bubble is open."
   Right: once the panel is open, the button has done its job and only competes
   with the form's own Add/Cancel — two ways to close, one of which (clicking the
   trigger again) is invisible as a close affordance. The Cancel inside the panel
   IS the close. Pure CSS via details[open], so no JS and no CSP exposure.
   summary is kept in the DOM (display:none on it would break the disclosure in
   some engines and remove the keyboard target), so it collapses to zero height
   instead. */
.add-inline[open] > summary {
  height: 0; padding: 0; margin: 0;
  overflow: hidden; opacity: 0;
  pointer-events: none;
}
/* ...but a keyboard user must still be able to reach it. When focused it comes
   back, so tabbing to it is not a dead end. */
.add-inline[open] > summary:focus-visible {
  height: auto; padding: 7px 14px; opacity: 1; pointer-events: auto;
}
/* with the trigger gone the panel is the whole control: no top gap needed */
.add-inline[open] > .confirm-body { margin-top: 0; }
/* the Add form drops below the header, full width of the panel */
.add-inline .confirm-body { margin-top: 12px; max-width: 560px; }

/* --- :target show/hide (five tabs) ------------------------------------------
   Mailboxes shown by default; aliases + configuration + deleted + audit hidden.
   Clicking a tab sets the URL fragment; #tab-X:target shows panel X and (via
   :has, baseline-supported) hides mailboxes. Without :has the panels simply
   stack — still fully usable — so the toggle is a progressive enhancement. */
.panel-aliases,
.panel-configuration,
.panel-deleted,
.panel-audit { display: none; }                    /* hidden by default */
.panel-mailboxes { display: block; }               /* shown by default */
#tab-aliases:target,
#tab-configuration:target,
#tab-deleted:target,
#tab-audit:target { display: block; }              /* targeted -> show */
/* mailboxes hides when ANY other tab is targeted */
.card.tabs:has(#tab-aliases:target) .panel-mailboxes,
.card.tabs:has(#tab-configuration:target) .panel-mailboxes,
.card.tabs:has(#tab-deleted:target) .panel-mailboxes,
.card.tabs:has(#tab-audit:target) .panel-mailboxes { display: none; }

/* force-config: server-side "show the Configuration panel" for dns-check
   responses (fragment survival across form submits is browser-dependent).
   :not(:has(:target)) makes these yield the moment the user targets ANY tab
   explicitly, so no two panels ever stack. */
.card.tabs.force-config:not(:has(.tabpanel:target)) .panel-configuration { display: block; }
.card.tabs.force-config:not(:has(.tabpanel:target)) .panel-mailboxes { display: none; }
.card.tabs.force-config:not(:has(.tabpanel:target)) .tab-mailboxes { color: var(--meta); border-bottom-color: transparent; }
.card.tabs.force-config:not(:has(.tabpanel:target)) .tab-configuration { color: var(--taupe); border-bottom-color: var(--tan); }

/* tab highlight: default highlights mailboxes; :target moves it to the chosen tab */
.tab-mailboxes { color: var(--taupe); border-bottom-color: var(--tan); }
.card.tabs:has(#tab-aliases:target) .tab-mailboxes,
.card.tabs:has(#tab-configuration:target) .tab-mailboxes,
.card.tabs:has(#tab-deleted:target) .tab-mailboxes,
.card.tabs:has(#tab-audit:target) .tab-mailboxes { color: var(--meta); border-bottom-color: transparent; }
.card.tabs:has(#tab-aliases:target) .tab-aliases { color: var(--taupe); border-bottom-color: var(--tan); }
.card.tabs:has(#tab-configuration:target) .tab-configuration { color: var(--taupe); border-bottom-color: var(--tan); }
.card.tabs:has(#tab-deleted:target) .tab-deleted { color: var(--taupe); border-bottom-color: var(--tan); }
.card.tabs:has(#tab-audit:target) .tab-audit { color: var(--taupe); border-bottom-color: var(--tan); }

/* ===========================================================================
   Newsletter workspace tabs (own :target set, parallel to the domain-detail
   tabs above but with distinct panel classes so the two never collide). Five
   tabs; lists shown by default. Same progressive-enhancement contract: without
   :has support the panels simply stack and stay usable.
   =========================================================================== */
.nlpanel-templates,
.nlpanel-mailings,
.nlpanel-settings,
.nlpanel-readiness { display: none; }
.nlpanel-lists { display: block; }
#nl-templates:target,
#nl-mailings:target,
#nl-settings:target,
#nl-readiness:target { display: block; }
/* #nl-lists is the default panel AND a real :target (the list tabs link to
   ?list=<slug>#nl-lists to stay on this panel across a reload). It therefore
   needs no :target rule of its own — it is visible unless another panel is
   targeted, which is exactly right. */
.card.tabs:has(#nl-templates:target) .nlpanel-lists,
.card.tabs:has(#nl-mailings:target) .nlpanel-lists,
.card.tabs:has(#nl-settings:target) .nlpanel-lists,
.card.tabs:has(#nl-readiness:target) .nlpanel-lists { display: none; }
/* tab highlight */
.tab-nl-lists { color: var(--taupe); border-bottom-color: var(--tan); }
.card.tabs:has(#nl-templates:target) .tab-nl-lists,
.card.tabs:has(#nl-mailings:target) .tab-nl-lists,
.card.tabs:has(#nl-settings:target) .tab-nl-lists,
.card.tabs:has(#nl-readiness:target) .tab-nl-lists { color: var(--meta); border-bottom-color: transparent; }
.card.tabs:has(#nl-templates:target) .tab-nl-templates { color: var(--taupe); border-bottom-color: var(--tan); }
.card.tabs:has(#nl-mailings:target) .tab-nl-mailings { color: var(--taupe); border-bottom-color: var(--tan); }
.card.tabs:has(#nl-settings:target) .tab-nl-settings { color: var(--taupe); border-bottom-color: var(--tan); }
.card.tabs:has(#nl-readiness:target) .tab-nl-readiness { color: var(--taupe); border-bottom-color: var(--tan); }

/* ---------------------------------------------------------------------------
   List selector bar (inside the Lists panel). These are LINKS carrying
   ?list=<slug>, not :target panels: only the selected list's members are
   fetched per page load, so the server decides which table to render. A
   :target approach would need every list's members in the DOM at once — N+1
   API calls to show one table.
   --------------------------------------------------------------------------- */
.nl-listbar {
  display: flex; flex-wrap: wrap; gap: 4px 6px;
  border-bottom: 1px solid var(--line);
  margin: 0 0 16px; padding-bottom: 10px;
}
.nl-listtab {
  padding: 5px 12px; border: 1px solid var(--line); border-radius: 999px;
  font-size: 13px; color: var(--meta); text-decoration: none; background: var(--white);
}
.nl-listtab:hover { color: var(--taupe); text-decoration: none; border-color: var(--tan); }
.nl-listtab.is-current { color: var(--white); background: var(--tan); border-color: var(--tan); }
.nl-listtab.is-current .muted { color: rgba(255,255,255,.8); }
/* An archived list stays reachable (its members and history are intact) but
   reads as inactive — it is out of Compose, so it should look out of the way. */
.nl-listtab.is-archived { opacity: .6; font-style: italic; }
.nl-archived-tag { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; margin-left: 4px; }

.nl-list-head { align-items: flex-start; }
.nl-list-head h3 { margin: 0; }
.nl-list-desc { margin: 2px 0 0; font-size: 13px; }
.nl-list-actions { display: flex; gap: 6px; align-items: flex-start; }

/* ---------------------------------------------------------------------------
   Import bubble. <details>/<summary> is the house disclosure (same as Compose
   mailing) and needs no JS — which the panel's CSP requires (script-src 'self',
   no inline JS). Closing the disclosure IS cancelling; the explicit Cancel
   button is a plain type="reset" for discoverability.
   Wider than the default .confirm-body: it holds three alternative inputs and a
   textarea, and cramping them makes the "any one of these" relationship harder
   to read.
   --------------------------------------------------------------------------- */
.nl-import .confirm-body { max-width: 560px; }
/* "or" divider between the paste box and the CSV upload — makes the two inputs
   read as alternatives rather than a form to fill top-to-bottom. */
.nl-import-or {
  display: flex; align-items: center; gap: 10px;
  margin: 14px 0; color: var(--meta); font-size: 12px;
}
.nl-import-or::before, .nl-import-or::after {
  content: ""; flex: 1; height: 1px; background: var(--line);
}
.nl-import-note  { margin: 10px 0 12px; font-size: 12px; }
.nl-import-buttons { display: flex; gap: 8px; align-items: center; }
.nl-import input[type=file] { font-size: 13px; }
/* A checkbox with a long explanation beside it: align the box to the first line
   rather than centring it against the whole wrapped block. */
.nl-checkline { display: flex; gap: 8px; align-items: flex-start; font-size: 13px; }
.nl-checkline input[type=checkbox] { margin-top: 3px; flex: none; }
.nl-danger-row { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }

/* Live short-name preview. Quiet by default (it is a hint, not an alarm); turns
   sage when it resolves and terracotta only when the input genuinely cannot
   become a slug. The colour is redundant with the text — the sentence says what
   happened on its own. */
.nl-slug-hint { margin: 5px 0 0; font-size: 12px; color: var(--meta); }
.nl-slug-ok   { color: #6f8f5b; font-family: var(--mono, monospace); }
.nl-slug-bad  { color: var(--danger); }

/* Progress + opt-out mini-bars in the mailings table. */
/* --panel was never declared: this bar's track has been rendering transparent
   since it was written (a var() with no declaration and no fallback resolves to
   nothing). Pre-existing, found by an undeclared-variable sweep while fixing the
   textarea border. --sand is the token for a recessed surface. */
.nl-bar { display: inline-block; width: 80px; height: 8px; background: var(--sand);
  border: 1px solid var(--line); border-radius: 4px; overflow: hidden; vertical-align: middle; }
.nl-bar-fill { display: block; height: 100%; background: var(--tan); }
.nl-bar-optout .nl-bar-fill { background: #b06a5a; }
.nl-status-done   { color: #4a7a4a; }
.nl-status-sending{ color: var(--taupe); }
.nl-status-draft  { color: var(--meta); }
.nl-status-failed { color: #b06a5a; }

/* ===========================================================================
   Domain summary bar + usage bars + configuration blocks (mailbox-activity).
   =========================================================================== */

/* Summary bar above the tabs: a row of labelled rollups. Wraps on narrow
   viewports. Sits on the warm panel tint to read as a header band. */
.summary {
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
  padding: 14px 20px;
  margin-bottom: 14px;
  background: var(--white);
  border: 1px solid var(--line);
  border-left: 3px solid var(--tan);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.summary-item { display: flex; flex-direction: column; gap: 3px; min-width: 110px; }
.summary-label { color: var(--meta); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; }
.summary-value { color: var(--ink); font-size: 16px; }
.summary-of { color: var(--meta); font-size: 13px; }

/* Progress bar (storage usage). Track is the warm panel tint; fill is the tan
   accent, shifting to amber then danger as it approaches the limit. */
.bar {
  height: 6px;
  background: var(--sand);
  border-radius: 3px;
  overflow: hidden;
  margin-top: 5px;
  min-width: 90px;
}
.bar-sm { height: 5px; margin-top: 4px; min-width: 70px; }
.bar-fill {
  height: 100%;
  background: var(--tan);
  border-radius: 3px;
  transition: width 0.3s ease;
}
.bar-fill.bar-warn { background: #c2922e; }   /* amber: >=80% (warm, matches palette) */
.bar-fill.bar-crit { background: var(--danger); } /* danger red: >=95% */

/* Mailbox table usage cell: number on one line, thin bar under it. */
.usage-cell { white-space: nowrap; }
/* Outbound counters ("0 (0) / 3 (5)") wrap badly in the narrow column —
   the last remaining multi-line cell after the 2026-07-02 density pass. */
.outbound-cell { white-space: nowrap; }
.usage-num { font-size: 13px; color: var(--body); }
.never { color: var(--meta); font-style: italic; }
.mono-sm { font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; font-size: 12px; }

/* Configuration tab: stacked setting blocks, divided by hairlines instead of
   separate cards (they're already inside the tab card). */
/* Each Configuration section is a framed box (2026-07-02: hairline-only
   separation read as one undifferentiated wall). These sit INSIDE the tabs
   .card, so the frame comes from the border alone — no nested shadow. Warn/
   danger keep their accent edge like .card-warn/-danger. */
.config-block {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px 22px;
  margin-bottom: 18px;
}
.config-block > h2:first-child { margin-top: 0; }
.config-warn   { border-left: 3px solid var(--tan); }
.config-danger { border-left: 3px solid var(--danger); }
.config-warn h2 { color: var(--danger); }
.config-danger h2 { color: var(--danger); }

/* ===========================================================================
   Add-mailbox form: inline address builder + password-match feedback.
   =========================================================================== */
/* local-part input followed by the @domain suffix on one line */
.addr-row { display: flex; align-items: stretch; }
.addr-row input {
  flex: 1 1 auto;
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  border-right: none;
}
.addr-domain {
  display: flex; align-items: center;
  padding: 0 12px;
  background: var(--sand);
  color: var(--taupe);
  border: 1px solid var(--line);
  border-top-right-radius: var(--radius);
  border-bottom-right-radius: var(--radius);
  font-size: 14px;
  white-space: nowrap;
}

/* password-match message */
.pw-match-msg.pw-ok  { color: #4a5a36; }   /* sage green, matches status dots */
.pw-match-msg.pw-bad { color: var(--danger); }

/* Field-level validation error: marks the input the server rejected and the
   message under it, so the admin can see WHICH field is wrong without reading
   the page-top banner. Set server-side on re-render (see domains/detail.php). */
.input-bad { border-color: var(--danger); }
.input-bad:focus { outline-color: var(--danger); }
.hint.field-error { color: var(--danger); }

/* Button that looks like a link — used for the "Did you mean <ascii>?" fill
   action, which must be a <button> for keyboard/AT semantics but should not
   read as a second submit control. */
.linklike {
  background: none; border: 0; padding: 0;
  color: var(--danger); font: inherit; text-decoration: underline; cursor: pointer;
}

/* disabled submit (JS sets this when passwords differ) */
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* ===========================================================================
   DKIM card: grouped record box, monospace fields, notes.
   =========================================================================== */
.record-box {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  padding: 16px 18px;
  margin: 16px 0;
}
.record-box-head {
  font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px;
  color: var(--meta); margin-bottom: 12px;
}
.record-grid { display: flex; flex-direction: column; gap: 10px; }
.record-row { display: flex; align-items: center; gap: 12px; }
.record-row-value { align-items: flex-start; }
.record-key {
  flex: 0 0 92px; font-size: 13px; color: var(--taupe); font-weight: bold;
  padding-top: 2px;
}
.record-val { flex: 1 1 auto; }
.record-val.short { max-width: 110px; flex: 0 0 110px; }
.record-tip { margin: 14px 0 0; font-size: 12.5px; line-height: 1.6; }

/* value textarea + its Copy button stacked; button top-right of the field */
.record-val-wrap { flex: 1 1 auto; position: relative; }
.record-val-wrap textarea, .record-val-wrap input { width: 100%; box-sizing: border-box; padding-right: 64px; }
.copy-btn { white-space: nowrap; }
.record-row .copy-btn { flex: 0 0 auto; align-self: center; }
.record-val-wrap .copy-btn {
  position: absolute; top: 6px; right: 6px; z-index: 1;
  background: var(--white); border: 1px solid var(--line);
}

/* the secondary "split form" box, set off from the primary record */

textarea.mono, input.mono {
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  font-size: 12.5px;
}
textarea.record-val { line-height: 1.5; word-break: break-all; resize: vertical; }

.dkim-note {
  margin-top: 16px; padding: 12px 14px;
  background: var(--sand); border-radius: var(--radius);
  font-size: 13px; color: var(--body); line-height: 1.6;
}
.dkim-foot { margin-top: 12px; font-size: 12px; }
code {
  background: var(--sand); padding: 1px 5px; border-radius: 3px;
  font-family: "SFMono-Regular", Consolas, monospace; font-size: 12px;
}

/* DKIM split: each chunk in its own framed block with a summary line on top */
.dns-entry {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--white);
  padding: 10px 12px;
  margin: 12px 0;
}
.dns-entry-head {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px;
  margin-bottom: 8px; font-size: 12.5px;
}
.dns-entry-name { font-family: "SFMono-Regular", Consolas, monospace; color: var(--taupe); font-weight: bold; }
.dns-entry-type {
  background: var(--sand); color: var(--taupe);
  padding: 0 7px; border-radius: 3px; font-weight: bold; font-size: 11px;
}
.dns-entry-ttl { color: var(--meta); }

/* ===========================================================================
   Mail DNS check: overall banner, per-record rows with status badges.
   =========================================================================== */
.dns-overall { padding: 10px 14px; border-radius: var(--radius); margin: 14px 0 6px; }
.dns-overall.dns-pass { background: #eef3e8; color: #3f5a2e; }
.dns-overall.dns-warn { background: #f6f0e2; color: #6f5b2e; }
.dns-overall.dns-fail { background: #f6e7e3; color: #7a3b2e; }
.dns-resolver { font-size: 12px; margin: 0 0 12px; }

.dns-results { list-style: none; margin: 0; padding: 0; }
.dns-row {
  display: grid;
  grid-template-columns: 86px 140px 1fr;
  align-items: baseline; gap: 10px;
  padding: 9px 0; border-top: 1px solid var(--line); font-size: 13px;
}
.dns-row:first-child { border-top: none; }
/* the run-check form: button + optional one-off resolver input */
.dns-run-form { display: flex; gap: 8px; align-items: center; margin-top: 10px; }
.dns-run-form input[type="text"] { max-width: 240px; font-size: 13px; }
/* the record actually found in DNS, shown under the detail text */
.dns-found { grid-column: 2 / -1; display: block; margin-top: 3px;
             color: var(--meta); word-break: break-all; }
.dns-badge {
  justify-self: start; font-size: 11px; font-weight: bold; letter-spacing: 0.5px;
  padding: 2px 8px; border-radius: 3px; color: #fff;
}
.dns-pass  .dns-badge { background: #6f8f5b; }
.dns-warn  .dns-badge { background: #c2a24a; }
.dns-fail  .dns-badge { background: #b5603f; }
.dns-missing .dns-badge { background: #9a8f7a; }
.dns-label  { font-weight: bold; color: var(--taupe); }
.dns-detail { color: var(--body); line-height: 1.5; }

@media (max-width: 560px) {
  .dns-row { grid-template-columns: 70px 1fr; }
  .dns-row .dns-detail { grid-column: 1 / -1; }
}

/* --- mailbox table: zebra + below-row edit panel (2026-07-02) ---------------
   Zebra classes come from a PHP counter in the template, NOT :nth-child —
   the expanded edit row must share its PARENT row's shade (the pair reads as
   one unit), and an inserted row would flip nth-child parity below it. */
.data tr.zebra > td { background: #ece7db; }   /* warm tint, clearly visible vs #faf9f7 page */
.data tr.mbx-row.editing > td { border-bottom: none; }   /* row + panel merge */

/* the full-width edit panel row under a mailbox row */
.edit-row > td { padding: 12px 14px 10px; }
.edit-inline {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: flex-end;                /* fields + buttons on one baseline */
}
.edit-inline .field { margin-bottom: 0; min-width: 200px; flex: 1 1 200px; }
.edit-inline .edit-actions { display: flex; gap: 8px; align-items: center; }
.edit-hint { text-align: left; margin: 8px 0 0; }

/* Out 24h coverage footnote on the domains list (2026-07-02) */
.out-coverage { text-align: left; margin: 6px 2px 0; }

/* ---- CSP-conformance utility classes (2026-07-06) ----------------------
   The panel CSP forbids inline style= attributes (style-src 'self'). These
   small purpose-named classes replace the handful of inline styles the
   templates used to carry, so the look is preserved without loosening the
   policy. Dynamic widths (progress/quota bars) are handled separately in
   panel.js via data-width-pct, since their value is per-request. */
.mark-dot     { color: var(--tan); }            /* the "·" in GENSYS·MAIL */
.error-code   { font-size: 32px; color: var(--tan); }
.card-narrow  { max-width: 480px; }             /* admins/create card */
.card-wide    { max-width: 520px; }             /* domains/create card */
.field-full   { width: 100%; }                  /* full-width input/textarea */
.mt-1         { margin-top: 4px; }
.mt-3         { margin-top: 14px; }
.mt-4         { margin-top: 18px; }
.text-center  { text-align: center; }
/* Brand link in the top bar must not look like a link (was color:inherit). */
.mark-link    { color: inherit; text-decoration: none; }

/* ---- HTML body rich editor (contenteditable) -----------------------------
   Progressive enhancement over the raw body_html textarea. Default (no JS):
   the toolbar/surface carry the `hidden` attribute and the textarea shows, so
   the operator hand-writes HTML exactly as before. When panel.js runs it adds
   `.html-editor-on` to the [data-html-editor] wrapper, which flips the display:
   textarea hides, toolbar + editable surface appear. Styled from this served
   stylesheet (style-src 'self') — no inline styles. */
[data-html-editor].html-editor-on .html-raw { display: none; }

.html-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 6px;
}
.html-tb {
  font: inherit;
  font-size: 0.85rem;
  line-height: 1;
  padding: 5px 9px;
  background: #f4efe4;
  border: 1px solid #c4b89c;
  border-radius: 4px;
  cursor: pointer;
  color: #4a4032;
}
.html-tb:hover { background: #e9e1cf; }
.html-tb:active { background: #ddd2b8; }

.html-surface {
  min-height: 11rem;
  padding: 10px 12px;
  border: 1px solid #c4b89c;
  border-radius: 4px;
  background: #fff;
  overflow-y: auto;
  font: inherit;
}
.html-surface:focus {
  outline: 2px solid #8a7a55;
  outline-offset: -1px;
}
/* Sensible defaults for content typed into the surface. */
.html-surface h2 { font-size: 1.2rem; margin: 0.4em 0; }
.html-surface p  { margin: 0.5em 0; }
.html-surface ul, .html-surface ol { margin: 0.5em 0 0.5em 1.4em; }
.html-surface a  { color: #5a6ea0; }
