/* Simple Modern Design Language — Simple Modern Datacenter.

   ONE stylesheet shared in spirit by every product: calm and white-dominant,
   the system SF stack, hairline borders, gentle shadows, generous whitespace,
   and exactly ONE accent per product (Simple Modern Datacenter violet). The
   token block below is identical in both product repositories apart from that
   accent ramp — if you change a value here, change it there. The accent ramp
   is the same one app/shell.py declares, character for character; a test
   compares the two, because the stylesheet is what the browser reads.

   Light and dark are both first class: the palette follows the reader's system
   setting via prefers-color-scheme, and an explicit data-theme on <html> wins
   in either direction. Every token is defined on bare :root first, so nothing
   depends on a media query having matched. */

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

:root {
  color-scheme: light;

  /* surfaces */
  --canvas: #f3f5f7;
  --sunken: #f3f5f7;
  --card: #ffffff;
  --side: #ffffff;
  --field: #ffffff;

  /* hairlines — the only borders this language draws */
  --hair: #dfe3e8;
  --hair-soft: #e8ebef;
  --ring: var(--accent);

  /* ink */
  --ink: #111418;
  --ink-2: #3d4550;
  /* Same failing grey as --ink-3 carried under a second name: the token was
     changed and the pages did not, because most quiet text reads --muted.
     Kept in step deliberately — two names for one ink must not drift. */
  --muted: #616a7b;

  /* interaction */
  --hover: #f3f5f7;
  --selected: var(--accent-soft);
  --btn2: #f8f9fb;

  /* chrome surfaces — what the shared shell (smdl-shell.css) paints with */
  --surface: #ffffff;
  --surface-2: #f8f9fb;
  --surface-3: #eef1f4;
  /* Measured against every light surface this token is painted on: at #6b7488 it
     failed WCAG AA (4.5:1) on five of six — surface-2 4.19, surface-3 3.93,
     good-soft 4.17, bad-soft 4.10, warn-soft 4.27. #616a7b clears all of them,
     worst case 4.57 on surface-3. Dark mode already passes and is untouched.
     Changed in all six siblings together: the family's own test asserts that
     nothing but the accent differs between products. */
  --ink-3: #616a7b;

  /* status — the same three hues in both products, used sparingly */
  --good: #08764f;  --good-soft: #e6f4ee;
  --bad: #b3261e;   --bad-soft: #fbeae8;
  --warn: #8a5a06;  --warn-soft: #fdf3e3;

  /* THE ONE THING A PRODUCT CHANGES */
  --accent: #923fcb;
  --accent-ink: #7c36ad;
  --accent-deep: #6e2f9b;
  --accent-soft: #f0e1ff;
  --accent-quiet: rgba(146, 63, 203, 0.10);
  --on-accent: #ffffff;
  /* The application's deep cut, for a brand band on a page that has no shell,
     and the lifted variant the seat is lit in on a near-black surface. */
  --app-sidebar: #33194a;
  --app-dark: #bc85f0;
  --live: var(--accent-deep);
  --live-soft: var(--accent-soft);

  /* elevation, radii, type */
  --shadow-card: 0 0 0 1px var(--hair);
  --shadow-pop: 0 8px 24px rgba(17,19,24,.08);
  /* The shell declares these too, and loads after this file — so declaring a
     different value here meant this stylesheet's geometry never applied. Same
     values, stated once per product so the token is visible where it is used. */
  --radius: 8px;
  --radius-sm: 6px;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto,
          Helvetica, Arial, "Helvetica Neue", sans-serif;

  /* v6 (DESIGN.md §3) */
  --line: #dfe3e8;
  --line-strong: #c3cad3;
  --line-soft: #e8ebef;
  --mark-quiet: #c8cfd8;
  --inset: #f3f5f7;
  --ink-4: #838c98;
  --ok: #08764f;
  --ok-soft: #e6f4ee;
  --danger: #b3261e;
  --danger-soft: #fbeae8;
  --info: #476780;
  --info-soft: #e9eff4;
  --off: #838c98;
  --off-soft: #eef1f4;
  --scrim: rgba(45,49,47,.40);
  --shadow-dlg: 0 18px 48px rgba(17,19,24,.14);
  --radius-lg: 10px;
  --radius-badge: 4px;
  --row: 44px;
  --row-dense: 40px;
  --row-two: 48px;
  --ctl: 32px;
  --ctl-dense: 28px;
  --ctl-lg: 36px;
  --w-fly-s: 400px;
  --w-fly-m: 480px;
  --w-fly-l: 640px;
  --pane: 380px;
  --pane-head: 44px;
  --pane-foot: 36px;
  --ease: cubic-bezier(.2,0,0,1);
  --dur-fly: 180ms;
  --dur-scrim: 120ms;
  --dur-exit: 120ms;
  --dur-swap: 90ms;
  --dur-toast: 160ms;
  --z-menu: 900;
  --z-fly: 1000;
  --z-confirm: 1050;
  --z-toast: 1100;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --canvas: #0c1016;
    --sunken: #10151d;
    --card: #151a23;
    --side: #151a23;
    --field: #10151d;

    --hair: #1f2630;
    --hair-soft: #1a2029;
    --ring: var(--accent);

    --ink: #edf0f6;
    --ink-2: #ccd4e2;
    --muted: #98a2b6;

    --hover: #1b212b;
    --selected: var(--accent-soft);
    --btn2: #1b212b;

    /* chrome surfaces — what the shared shell (smdl-shell.css) paints with */
    --surface: #151a23;
    --surface-2: #1b212b;
    --surface-3: #222937;
    --ink-3: #98a2b6;

    --good: #5fc88c;  --good-soft: #12251c;
    --bad: #fc6474;   --bad-soft: #2c1417;
    --warn: #e3b341;  --warn-soft: #2a2311;

    /* The accent lifts for a dark canvas — the same hue, not a different one.
       Leaving --accent at its light value made every filled control muddy. */
    --accent: #bc85f0;
    --accent-ink: #d7b6f6;
    --accent-deep: var(--accent-ink);
    --accent-soft: #2c1b3a;
    --accent-quiet: rgba(188, 133, 240, 0.16);
    --on-accent: #1a0c2b;
    --app-sidebar: #33194a;
    --app-dark: #bc85f0;

    --shadow-card: 0 0 0 1px var(--hair);
    --shadow-pop: 0 8px 24px rgba(0,0,0,.45);
  
  /* v6 (DESIGN.md §3) */
  --line: #1f2630;
  --line-strong: #2c3542;
  --line-soft: #1a2029;
  --mark-quiet: #39424f;
  --inset: #10151d;
  --ink-4: #6b7688;
  --ok: #5fc88c;
  --ok-soft: #12251c;
  --danger: #fc6474;
  --danger-soft: #2c1417;
  --info: #8fa9be;
  --info-soft: #18222b;
  --off: #6b7688;
  --off-soft: #1b212b;
  --scrim: rgba(0,0,0,.55);
  --shadow-dlg: 0 18px 48px rgba(0,0,0,.6);
}
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --canvas: #0c1016;
  --sunken: #10151d;
  --card: #151a23;
  --side: #151a23;
  --field: #10151d;

  --hair: #1f2630;
  --hair-soft: #1a2029;
  --ring: var(--accent);

  --ink: #edf0f6;
  --ink-2: #ccd4e2;
  --muted: #98a2b6;

  --hover: #1b212b;
  --selected: var(--accent-soft);
  --btn2: #1b212b;

  /* chrome surfaces — what the shared shell (smdl-shell.css) paints with */
  --surface: #151a23;
  --surface-2: #1b212b;
  --surface-3: #222937;
  --ink-3: #98a2b6;

  --good: #5fc88c;  --good-soft: #12251c;
  --bad: #fc6474;   --bad-soft: #2c1417;
  --warn: #e3b341;  --warn-soft: #2a2311;

  /* The accent lifts for a dark canvas — the same hue, not a different one.
     Leaving --accent at its light value made every filled control muddy. */
  --accent: #bc85f0;
  --accent-ink: #d7b6f6;
  --accent-deep: var(--accent-ink);
  --accent-soft: #2c1b3a;
  --accent-quiet: rgba(188, 133, 240, 0.16);
  --on-accent: #1a0c2b;
  --app-sidebar: #33194a;
  --app-dark: #bc85f0;

  --shadow-card: 0 0 0 1px var(--hair);
  --shadow-pop: 0 8px 24px rgba(0,0,0,.45);

  /* v6 (DESIGN.md §3) */
  --line: #1f2630;
  --line-strong: #2c3542;
  --line-soft: #1a2029;
  --mark-quiet: #39424f;
  --inset: #10151d;
  --ink-4: #6b7688;
  --ok: #5fc88c;
  --ok-soft: #12251c;
  --danger: #fc6474;
  --danger-soft: #2c1417;
  --info: #8fa9be;
  --info-soft: #18222b;
  --off: #6b7688;
  --off-soft: #1b212b;
  --scrim: rgba(0,0,0,.55);
  --shadow-dlg: 0 18px 48px rgba(0,0,0,.6);
}

html, body { max-width: 100%; overflow-x: hidden; }

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a { color: inherit; text-decoration: none; }
a:hover { text-decoration: none; }
h1, h2, h3, h4 { letter-spacing: -0.02em; font-weight: 640; margin: 0; }
p { margin: 0; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-sm); }

code, .mono { font-family: var(--mono); font-size: 0.92em; }
code { background: var(--selected); border-radius: 5px; padding: 1px 5px; }

/* ------------------------------------------------------------------ shell */

/* The shell grid, corner switcher, top bar, sidebar and canvas all come from
   smdl-shell.css — the SAME file CORE serves, so the family is one chrome by
   construction. This stylesheet keeps only what the shell does not carry: the
   profile popover, the signed-out header, and this product's page furniture. */

.avatar {
  width: 28px; height: 28px; border-radius: 50%; flex: none;
  background: var(--accent-quiet); color: var(--accent-deep);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 680; letter-spacing: 0;
}

/* profile popover — mirrors CORE's, on this stylesheet's tokens */
.user-menu { position: relative; }
.user-pop {
  position: absolute; top: calc(100% + 8px); right: 0;
  min-width: 260px; padding: 8px; border-radius: var(--radius);
  background: var(--surface); box-shadow: var(--shadow-pop);
  z-index: 60;
}
.user-pop[hidden] { display: none; }
.user-pop-id { display: flex; align-items: center; gap: 11px; padding: 10px 10px 14px; }
.user-pop-who { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.user-pop-who b { font-size: 14px; }
.user-pop-who small { color: var(--ink-3); font-size: 12px; overflow: hidden; text-overflow: ellipsis; }
.user-pop-appearance { padding: 2px 10px 16px; }
.user-pop-label { display: block; color: var(--ink-3); font-size: 11.5px; font-weight: 650; margin-bottom: 8px; }
.theme-seg {
  display: flex; width: 100%; padding: 3px; gap: 2px;
  border: 0; box-shadow: inset 0 0 0 1px var(--hair);
  border-radius: var(--radius-sm); background: var(--surface-2);
}
.theme-seg button {
  flex: 1; min-height: 30px; padding: 0; border: 0; border-radius: var(--radius-sm);
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  background: none; color: var(--ink-2); font-family: var(--sans);
  font-size: 12.5px; font-weight: 600; cursor: pointer;
}
.theme-seg button:hover { color: var(--ink); }
.theme-seg button[aria-pressed="true"] { background: var(--card); color: var(--ink); box-shadow: var(--shadow-card); }
.theme-seg button .ic { font-size: 14px; }
.user-pop-item {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  border: 0; background: none; font-family: var(--sans); font-size: 13px; font-weight: 550;
  color: var(--ink-2); padding: 9px 10px; border-radius: var(--radius-sm);
  cursor: pointer; text-decoration: none;
}
.user-pop-item .ic { font-size: 16px; opacity: 0.7; }
.user-pop-item:hover { background: var(--surface-2); color: var(--ink); }
.user-pop-item.danger-item:hover { color: var(--bad); background: var(--bad-soft); }
.user-pop form { margin: 0; }

/* the signed-out header (landing and error surfaces) */
.brand {
  display: flex; align-items: center; gap: 9px;
  font-weight: 660; letter-spacing: -0.02em; color: var(--ink);
  padding: 5px 8px; border-radius: var(--radius-sm);
}
.brand:hover { background: var(--hover); }
.mark { width: 24px; height: 24px; flex: none; color: var(--ink); }
.plain-actions { margin-left: auto; display: flex; gap: 8px; }

/* the page inside the shell canvas */
/* One measure for every page, and the same one in every product — this is
   part of the shared scale. Sites and Integrations each widened it to 1360px
   in their own stylesheet, so two pages were 180px wider than the rest and
   the canvas visibly jumped moving between them. Wide content scrolls inside
   its own .tablewrap instead. */
.page { max-width: 1180px; margin: 0 auto; padding: 0 4px 64px; }

/* A create or edit form is a single column of fields, and 760px is where that
   column stays comfortable to fill in -- a 1180px-wide input for a 200-character
   title helps nobody. The cap itself was right and was already in use, as an
   inline style repeated across ten templates. What was wrong is WHERE it sat:
   hard against the left of the 1180px measure, with 400px of nothing beside it
   on pages whose only content is that one card. It is centred in the measure
   now, and named, so the next form does not have to rediscover the number. */
.formpage { max-width: 760px; margin-inline: auto; }

/* ----------------------------------------------------------------- pieces */

.card {
  background: var(--card); border-radius: var(--radius);
  box-shadow: var(--shadow-card); padding: 20px;
}

/* Alerts are triaged separately from the configuration that creates them.
   Keep the two workspaces at one route, but never stack both into one page. */
.alert-modes {
  display: flex; gap: 24px; margin-bottom: 16px;
  border-bottom: 1px solid var(--hair);
}
.alert-modes a {
  position: relative; display: inline-flex; min-height: 40px; align-items: center;
  gap: 7px; color: var(--muted); font-size: 13px; font-weight: 620;
  text-decoration: none;
}
.alert-modes a::after {
  position: absolute; right: 0; bottom: -1px; left: 0; height: 2px;
  background: transparent; content: "";
}
.alert-modes a:hover, .alert-modes a.is-active { color: var(--ink); }
.alert-modes a.is-active::after { background: var(--accent); }
.alert-modes a span {
  display: inline-grid; min-width: 20px; height: 20px; padding-inline: 6px;
  place-items: center; border-radius: 999px; background: var(--surface-2);
  color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums;
}
.alert-view[hidden] { display: none; }
.alert-rules-card table.list th, .alert-rules-card table.list td { padding-block: 10px; }
.card + .card { margin-top: 16px; }
.card h2 { font-size: 15px; margin-bottom: 4px; }
.card .card-sub { color: var(--muted); font-size: 13px; }
.card-flush { padding: 0; overflow: hidden; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: var(--ctl-h, 34px); padding: 0 13px; border: 1px solid var(--hair);
  border-radius: var(--ctl-radius, 9px); background: var(--card); color: var(--ink);
  font-family: var(--sans); font-weight: var(--ctl-fw, 620); font-size: var(--ctl-fs, 13px);
  cursor: pointer; white-space: nowrap;
}
.btn:hover { background: var(--hover); }
/* A filled control carries text, so it takes the deeper step of the hue:
   the tile itself clears 4.5:1 against white in only four of the six
   products. --accent stays the graphical value. */
.btn-primary { background: var(--accent-deep); border-color: transparent; color: var(--on-accent); }
.btn-primary:hover { background: var(--accent-deep); filter: brightness(1.06); }
.btn-quiet { background: transparent; border-color: transparent; color: var(--muted); }
.btn-quiet:hover { background: var(--hover); color: var(--ink); }
/* Every Delete in this product wore the ordinary button, or `btn-secondary`,
   which is not a class this stylesheet defines — so the one control that
   cannot be undone looked exactly like Save beside it. */
.btn-danger { background: var(--bad-soft); border-color: transparent; color: var(--bad); }
.btn-danger:hover { background: var(--bad-soft); filter: brightness(0.97); }

/* Settings > Regions. Its markup used `.row`, `.between`, `.grow` and
   `.btn-secondary` — none of them classes any stylesheet here defines — so
   every row was a stack of unstyled block elements. */
.region-rename { display: flex; gap: 8px; align-items: center; min-width: 0; }
.region-rename input { flex: 1 1 160px; min-width: 0; }
/* A NAME AND THE BUTTON THAT TAKES IT. The field used to stretch the whole
   row -- a 997px text input for "us-west" -- and `align-items: flex-end`
   aligned the OUTER edges, so the field's 14px bottom margin pushed the button
   thirteen pixels below the input it belongs to. The field is sized to what it
   holds, the margin is dropped inside this row, and the two line up. */
.region-add { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; }
.region-add .field { flex: 0 1 300px; margin-bottom: 0; }
/* Named for a screen reader, invisible to everyone else. */
.vh { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
.btn-sm { height: var(--ctl-h-sm, 28px); padding: 0 10px; font-size: 12.5px; }

.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px;
  margin-bottom: 20px; }
.stat {
  background: var(--card); border-radius: var(--radius); box-shadow: var(--shadow-card);
  padding: 15px 16px;
}
.stat .n { font-size: 26px; font-weight: 640; letter-spacing: -0.03em; line-height: 1.15; }
.stat .k { color: var(--muted); font-size: 12.5px; margin-top: 2px; }
.stat.is-accent .n { color: var(--accent-ink); }

/* filters */
.filters {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  margin-bottom: 14px;
}
/* One height for everything in a filter row. It used to hold a 32px input, a
   34px button and an enhanced select trigger at whatever its content made it —
   three baselines across four controls that sit on one line. */
.filters select, .filters input[type="search"], .filters input[type="text"],
.filters input[type="date"] {
  width: auto; height: var(--ctl-h, 34px); border: 1px solid var(--hair);
  border-radius: var(--radius-sm);
  background: var(--card); color: var(--ink); font-family: var(--sans); font-size: 13px;
  padding: 0 10px; min-width: 0;
}
.filters .smdl-select-trigger { min-height: var(--ctl-h, 34px); }
.filters .btn { height: var(--ctl-h, 34px); }
.filters input[type="search"] { min-width: 190px; flex: 1 1 190px; max-width: 320px; }

/* type-ahead — the suggestions under the search field, fed by the search
   route's own ?format=json branch. The field is a plain form control and the
   form submits without any of this; the list is an accelerator, never the way
   in. The wrapper takes the flex the input had, because it is now the flex
   item. */
.ta { position: relative; flex: 1 1 190px; max-width: 320px; }
.ta input[type="search"] { width: 100%; max-width: none; flex: none; }
.ta-pop {
  position: absolute; z-index: 40; top: calc(100% + 8px); left: 0; right: 0;
  margin: 0; padding: 4px; list-style: none; background: var(--card);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-pop);
  max-height: 320px; overflow-y: auto;
}
.ta-pop[hidden] { display: none; }
.ta-pop li { margin: 0; }
.ta-pop a {
  display: flex; gap: 8px; align-items: baseline; padding: 7px 9px;
  border-radius: var(--radius-badge, 4px); font-size: 13px; color: var(--ink);
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.ta-pop a:hover, .ta-pop a.is-active { background: var(--hover); }
.ta-pop a small { color: var(--muted); font-size: 11.5px; margin-left: auto; flex: none; }

/* tables scroll inside themselves; the page never scrolls sideways */
.tablewrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table.list { width: 100%; border-collapse: collapse; font-size: 13.5px; min-width: 640px; }
table.list th {
  text-align: left; font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--muted); font-weight: 640; padding: 12px 16px; border-bottom: 1px solid var(--hair-soft);
  white-space: nowrap;
}
table.list td { padding: 13px 16px; border-bottom: 1px solid var(--hair-soft); vertical-align: middle; }
table.list tr:last-child td { border-bottom: 0; }
table.list tbody tr:hover { background: var(--hover); }
table.list .ref { font-family: var(--mono); font-size: 12.5px; color: var(--muted); white-space: nowrap; }
table.list .subject { font-weight: 550; color: var(--ink); }
table.list .subject a:hover { color: var(--accent-ink); }
table.list .num { text-align: right; font-variant-numeric: tabular-nums; }
table.list .when { color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; }

/* chips */
/* A BADGE, NOT A PILL. The chip was a 999px capsule at 650 weight, which is
   the one shape on the page that says "tap me" without being tappable -- and
   next to a card at 8px and a control at 6px it was the only fully round thing
   left. It is the mockup's badge now: the shared badge radius, a shorter box,
   and the weight down to 500, because the tint is what carries a status and
   the label does not also have to shout. The four custom properties stay, so
   a context that needs a bigger chip still says so in one place. */
.chip {
  display: inline-flex; align-items: center; gap: 5px; height: var(--chip-h, 20px);
  padding: 0 var(--chip-pad, 6px); border-radius: var(--radius-badge); font-size: var(--chip-fs, 12px);
  font-weight: var(--chip-fw, 500); letter-spacing: 0.01em;
  background: var(--selected); color: var(--ink-2); white-space: nowrap;
}
.chip .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.chip-accent { background: var(--accent-quiet); color: var(--accent-ink); }
.chip-quiet { background: transparent; color: var(--muted); border: 1px solid var(--hair); }
/* Priority and state read by weight, not by a second hue: the accent marks
   what is urgent and everything else stays neutral. */
.chip-p1 { background: var(--accent); color: var(--on-accent); }
.chip-p2 { background: var(--accent-quiet); color: var(--accent-ink); }
/* The component had no warning or error variant, so pages reached for
   `style="background:var(--warn-soft)"` inline — a background with no ink to
   go with it, so the text stayed at the neutral chip's colour on a tinted
   ground. Two variants, both carrying their own ink. */
.chip-warn { background: var(--warn-soft); color: var(--warn); }
.chip-bad { background: var(--bad-soft); color: var(--bad); }
.chip-good { background: var(--good-soft); color: var(--good); }

.pill-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }

/* The shell renders a `crumbs` block that no page in this product ever filled,
   so a detail page said where it was only through a "Back to …" button in the
   corner — which is a way out, not a place. Same rule as the family's. */
.crumbs { display: flex; gap: 6px; align-items: center; color: var(--muted); font-size: 12.5px;
  margin-bottom: 8px; flex-wrap: wrap; }
.crumbs a:hover { color: var(--ink); }
.crumbs span { opacity: .5; }

/* forms */
.field { display: block; margin-bottom: 14px; }
.field > .label {
  display: block; font-size: 12.5px; font-weight: 600; color: var(--ink-2); margin-bottom: 5px;
}
.field .help { font-size: 12px; color: var(--muted); margin-top: 5px; }
input[type="text"], input[type="email"], input[type="date"], input[type="search"],
input[type="file"], select, textarea {
  width: 100%; border: 1px solid var(--hair); border-radius: var(--radius-sm);
  background: var(--card); color: var(--ink); font-family: var(--sans); font-size: 13.5px;
  padding: 8px 11px; max-width: 100%;
}
textarea { min-height: 120px; resize: vertical; line-height: 1.55; }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: 0; border-color: transparent; }
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0 16px; }
.form-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.checkline { display: flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--ink-2); }
.checkline input { width: auto; }

/* inline control forms on a detail page */
.control { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.control select { flex: 1 1 140px; height: 32px; padding: 0 10px; }

/* two-column detail layout */
.split { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 16px; align-items: start; }
.aside { display: flex; flex-direction: column; gap: 16px; }
.aside .card h2 { font-size: 12.5px; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--muted); margin-bottom: 12px; }

.kv { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 8px 10px; font-size: 13px; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; color: var(--ink); overflow-wrap: anywhere; }

/* banners */
.banner {
  display: flex; gap: 10px; align-items: flex-start; padding: 11px 14px; border-radius: var(--radius-sm);
  font-size: 13.5px; margin-bottom: 16px; border: 1px solid var(--hair);
}
/* A refusal was a grey hairline and a success was painted in the product's
   accent, so "Saved." shouted and "That is not a date." whispered — the two
   exactly the wrong way round. Status colour comes from the status tokens, and
   a blocking warning gets the third one rather than reading as an aside. */
.banner-ok { background: var(--good-soft); border-color: transparent; color: var(--good); }
.banner-err { background: var(--bad-soft); border-color: transparent; color: var(--bad);
  font-weight: 550; }
.banner-warn { background: var(--warn-soft); border-color: transparent; color: var(--warn);
  font-weight: 550; }
.banner-info { background: var(--sunken); color: var(--ink-2); }

/* One inset. The same block sat in a flush card and in a padded one, so it was
   inset 20px in one place and 40px in another. */
.card:not(.card-flush) > .empty { padding-inline: 0; }
.empty { text-align: left; padding: 34px 20px; color: var(--muted); }
.empty h2 { font-size: 15px; color: var(--ink); margin-bottom: 6px; }
.empty p { max-width: 60ch; }

/* ------------------------------------------------- landing and standalone */

.plain { min-height: 100vh; display: flex; flex-direction: column; }
.plain-top { display: flex; align-items: center; gap: 12px; padding: 18px 24px; flex-wrap: wrap; }
.landing { width: 100%; max-width: 660px; margin: 0 auto; padding: 72px 24px 96px; }
.landing h1 { font-size: 40px; line-height: 1.08; font-weight: 680; letter-spacing: -0.03em;
  margin-bottom: 16px; }
.landing .lede { font-size: 17px; line-height: 1.6; color: var(--ink-2); margin-bottom: 28px; }
.ctas { display: flex; gap: 10px; flex-wrap: wrap; }
.cta {
  display: inline-flex; align-items: center; height: 40px; padding: 0 19px;
  border-radius: var(--radius-sm); background: var(--accent); color: var(--on-accent);
  font-weight: 600; font-size: 13.5px; border: 1px solid transparent;
}
.cta.ghost { background: var(--card); color: var(--ink); border-color: var(--hair); }
.hint { margin-top: 26px; color: var(--muted); font-size: 13px; }
.orglist { display: flex; flex-direction: column; gap: 8px; margin: 26px 0 0; }
.orglist a {
  display: flex; align-items: center; gap: 10px; padding: 13px 16px; border-radius: var(--radius);
  background: var(--card); box-shadow: var(--shadow-card); font-weight: 570;
}
.orglist a:hover { box-shadow: var(--shadow-pop); }
.orglist a .go { margin-left: auto; color: var(--muted); font-size: 12.5px; font-weight: 500; }

/* ------------------------------------------------------------ responsive */

/* 1280 and up gets the full three-zone shell above. */

@media (max-width: 1080px) {
  .split { grid-template-columns: minmax(0, 1fr); }
  .aside { flex-direction: row; flex-wrap: wrap; }
  .aside > .card { flex: 1 1 260px; }
}

/* 834 — tablet: the shell rail is handled by smdl-shell.css. */
@media (max-width: 900px) {
  .page { padding: 0 0 56px; }
}

/* 390 — phone. */
@media (max-width: 640px) {
  .page { padding: 0 0 48px; }
  .landing { padding: 44px 18px 72px; }
  .landing h1 { font-size: 30px; }
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kv { grid-template-columns: 84px minmax(0, 1fr); }
}

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

/* Platform notifications: a quick triage panel in the shell and a full inbox
   in the canvas. The event store is in CORE; this product only renders the
   signed-in person's deliveries and sends read state back through its own
   authenticated server. */
.platform-notif { position: relative; }
.platform-notif-bell { position: relative; }
.platform-notif-badge {
  position: absolute; top: 1px; right: 1px; min-width: 15px; height: 15px;
  padding: 0 4px; border-radius: 999px; background: var(--accent); color: var(--on-accent);
  box-shadow: 0 0 0 2px var(--canvas); font-size: 11px; line-height: 15px;
  text-align: center; font-weight: 700;
}
.platform-notif-panel {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 90; width: min(390px, calc(100vw - 28px));
  overflow: hidden; border-radius: var(--radius-lg); background: var(--card);
  box-shadow: 0 0 0 1px var(--hair), 0 20px 54px -18px rgba(8, 11, 16, .42);
}
.platform-notif-panel[hidden] { display: none; }
.platform-notif-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 48px; padding: 0 14px; border-bottom: 1px solid var(--hair-soft);
}
.platform-notif-head strong { font-size: 14px; }
.text-link {
  appearance: none; border: 0; padding: 4px; background: none; color: var(--accent-ink);
  font: inherit; font-size: 12px; font-weight: 620; cursor: pointer;
}
.platform-notif-tabs { display: flex; gap: 4px; padding: 8px 10px; border-bottom: 1px solid var(--hair-soft); }
.platform-notif-tabs button {
  appearance: none; border: 0; border-radius: var(--radius-sm); padding: 6px 10px; background: transparent;
  color: var(--muted); font: inherit; font-size: 12px; font-weight: 620; cursor: pointer;
}
.platform-notif-tabs button[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent-ink); }
.platform-notif-list { max-height: min(430px, 58vh); overflow-y: auto; }
.platform-notif-item {
  display: grid; grid-template-columns: 8px minmax(0, 1fr) auto; gap: 10px; align-items: start;
  padding: 12px 14px; color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--hair-soft);
}
.platform-notif-item:hover { background: var(--surface-2); }
.platform-notif-item .notif-dot { width: 7px; height: 7px; margin-top: 5px; border-radius: 50%; background: transparent; }
.platform-notif-item.is-unread .notif-dot { background: var(--accent); }
.platform-notif-copy { min-width: 0; }
.platform-notif-copy strong, .platform-notif-copy small { display: block; }
.platform-notif-copy strong { font-size: 12.5px; font-weight: 650; overflow-wrap: anywhere; }
.platform-notif-copy small { margin-top: 3px; color: var(--muted); font-size: 11.5px; line-height: 1.4; overflow-wrap: anywhere; }
.platform-notif-source { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .04em; }
.platform-notif-empty { padding: 28px 16px; color: var(--muted); text-align: center; font-size: 12.5px; }
.platform-notif-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 11px 14px; color: var(--accent-ink); text-decoration: none; font-size: 12.5px; font-weight: 620;
}
.notification-feed { display: grid; gap: 0; }
.notification-feed .platform-notif-item { grid-template-columns: 8px minmax(0, 1fr) auto; padding: 15px 16px; }
.notification-feed .platform-notif-item:last-child { border-bottom: 0; }

@media (max-width: 640px) {
  .platform-notif-panel { position: fixed; top: 58px; right: 10px; left: 10px; width: auto; }
  .platform-notif-item, .notification-feed .platform-notif-item {
    grid-template-columns: 8px minmax(0, 1fr);
  }
  .platform-notif-source { grid-column: 2; }
}
