/* ==========================================================================
   Milieu — design system stylesheet
   --------------------------------------------------------------------------
   The Milieu Family Services visual system, as specified in
   docs/brand-kit/milieu-style-guide.html. Drop-in for any app under the
   Milieu brand.

   Usage:
       <link rel="stylesheet" href="milieu.css">
   with assets/InterVariable.woff2 reachable at the url() below.

   Three principles cover almost every surface: ONE RADIUS (8px), ONE-PIXEL
   BORDERS, and NO SHADOWS. Depth is a border plus the split between
   `surface` and `surface-sunken` — that is the whole elevation model, and it
   stays crisp in dark mode where soft shadows turn to mud. Hover shifts tone
   only, never position: filled things dim, bordered things take the sunken
   fill. Nothing moves unless the user moved it.

   The colour firewall: blue is the only accent and carries every action;
   navy is the ink; gold and salmon are jewellery — the logo and the four-bar
   rule, and that is the whole list. Brand colours never encode data.
   ========================================================================== */

/* --- Type ---------------------------------------------------------------
   Inter, self-hosted. One variable file covers every weight — never load it
   from a CDN; this app is deliberately offline-capable and the habit is
   worth keeping. */
@font-face {
  font-family: "InterVariable";
  src: url("assets/InterVariable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ==========================================================================
   1. Tokens
   --------------------------------------------------------------------------
   Two layers, deliberately.

   The `--color-*` block is the CANONICAL Milieu vocabulary, copied verbatim
   from docs/brand-kit/milieu-tokens.css. It is the source of truth and the
   only place a literal brand hex appears.

   Everything after it is an ALIAS in this app's older vocabulary (--brand,
   --ink, --surface …), kept because app/globals.css and its ~1,800 lines of
   `lr-` components read those names. Aliases are var() references, not
   copies, so the dark theme only has to redeclare the canonical tokens and
   every alias follows for free.
   ========================================================================== */

:root {
  /* --- Brand ------------------------------------------------------------
     Blue carries every action (4.3:1 on white).
     Navy is the text and structural colour (17:1 on white).
     Gold (1.6:1) and salmon (2.7:1) are DECORATIVE ONLY — never text,
     never an icon that must be read, never a data encoding. */
  --color-brand-blue: #3d7cc0;
  --color-brand-blue-dark: #2d5d92;
  --color-brand-blue-light: #eaf1f9;
  --color-brand-salmon: #e08561;
  --color-brand-salmon-light: #fbeee8;
  --color-brand-gold: #f5cc24;
  --color-brand-gold-light: #fef8dc;
  --color-brand-navy: #0b1b34;
  --color-brand-navy-muted: #3a465e;

  /* --- Surfaces & text (light) ------------------------------------------ */
  --color-surface: #ffffff;
  --color-surface-sunken: #f7f8fa;
  --color-surface-raised: #ffffff;
  --color-border: #e2e5ea;
  --color-border-strong: #c7ccd4;
  --color-text: #0b1b34;
  --color-text-muted: #4f5a72;
  --color-text-subtle: #6d778e;

  /* --- Status / sentiment ------------------------------------------------
     Deliberately NOT brand colours: a reader should never have to learn a
     palette to read a result. The guide holds this whole ramp constant across
     both themes, on the grounds that every step clears 3:1 on both #ffffff
     and #131a29.

     ONE EXCEPTION, in the dark block below: --color-unfav-strong. 3:1 is the
     bar for a UI edge or large text, and this token is neither — it is the
     LABEL of the destructive button and the text of an error alert, at 14px.
     At #c0392b that reads 2.81:1 on the dark grounds it actually lands on,
     against the guide's own hard rule that body text clears 4.5:1 in both
     themes. So dark takes a lighter red. Every other step here is unchanged,
     in both themes, exactly as the guide specifies. */
  --color-fav-strong: #1c7f56;
  --color-fav: #27915f;
  --color-fav-light: #e6f4ed;
  --color-neutral-mid: #7b8492;
  --color-neutral-light: #f0f1f4;
  --color-unfav: #c4701c;
  --color-unfav-strong: #c0392b;
  --color-unfav-light: #fdeceb;

  /* --- Warning / caution ------------------------------------------------- */
  --color-warn: #b7791f;
  --color-warn-bg: #fdf6e3;
  --color-warn-border: #e8d08a;

  /* --- Shape & type ------------------------------------------------------ */
  --radius-card: 8px;
  --font-sans: "InterVariable", "Inter", ui-sans-serif, system-ui,
    -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  /* Focus rings and translucent brand washes need the channels separately,
     so they cannot just reference the hex. Redeclared in the dark block. */
  --brand-rgb: 61, 124, 192;

  /* ======================================================================
     Aliases — this app's existing token names, pointed at the canonical set.
     ====================================================================== */

  /* Brand. --brand-dark reads as "MORE EMPHATIC blue", not "darker blue":
     on a dark ground emphasis means stepping toward the light, which is why
     its value inverts between themes. Components need no branching. */
  --brand: var(--color-brand-blue);
  --brand-dark: var(--color-brand-blue-dark);
  --brand-bright: var(--color-brand-blue);   /* retired: no second accent */
  --brand-ink: var(--color-text);            /* headings are the ink */
  --brand-pale: var(--color-border-strong);  /* quiet rules and markers */
  --brand-tint: var(--color-brand-blue-light);
  --brand-tint-2: var(--color-brand-blue-light);

  /* Neutrals */
  --ink: var(--color-text);
  --ink-soft: var(--color-text-muted);
  --muted: var(--color-text-muted);
  --subtle: var(--color-text-subtle);
  --page-bg: var(--color-surface-sunken);
  --surface: var(--color-surface);
  --surface-2: var(--color-surface-sunken);
  --surface-3: var(--color-surface-raised);
  --border: var(--color-border);
  --line: var(--color-border);
  --border-input: var(--color-border-strong);
  --border-hover: var(--color-border-strong);
  --border-strong: var(--color-border-strong);

  /* Status */
  --success-bg: var(--color-fav-light);
  --success-border: var(--color-fav);
  --success-ink: var(--color-fav-strong);
  --warn-bg: var(--color-warn-bg);
  --warn-border: var(--color-warn-border);
  --warn-ink: var(--color-warn);
  --error-bg: var(--color-unfav-light);
  --error-border: var(--color-unfav-strong);
  --error-ink: var(--color-unfav-strong);
  --danger: var(--color-unfav-strong);
  --danger-dark: var(--color-unfav-strong);
  --danger-border-soft: var(--color-unfav-strong);
  --danger-wash: var(--color-unfav-light);

  /* Primary buttons are filled brand blue, and their label is whatever clears
     4.5:1 against it. In light that is white. In DARK it is not: the dark
     palette retints brand blue upward to #6ba3dd for the ground, and white on
     that is 2.1:1. The guide's accessibility floor — body text at least 4.5:1
     in both themes — outranks the literal `color: #ffffff` in its component
     sample, so the ink flips to navy in dark and the button stays the accent
     colour rather than being pinned to the light-mode blue. */
  --btn-ink: #ffffff;
  --btn-secondary-bg: transparent;
  --btn-secondary-ink: var(--color-text);
  --btn-secondary-hover: var(--color-surface-sunken);
  /* Control height, so a dense toolbar or an icon button can opt down
     without fighting the 46px floor an end-user control needs. */
  --btn-h: 46px;

  /* The "all good" icon tile. */
  --icon-good-bg: var(--color-fav-light);
  --icon-good-ink: var(--color-fav-strong);

  /* Chrome that used to be frosted glass is now simply a surface with a
     border. The names survive so no component has to change. */
  --glass-bg: var(--color-surface);
  --glass-border: var(--color-border);
  --glass-panel-bg: var(--color-surface);
  --glass-panel-border: var(--color-border);
  --overlay-bg: rgba(247, 248, 250, 0.92);
  --scrim: rgba(11, 27, 52, 0.45);
  --seam: var(--color-surface);

  /* Native form controls and scrollbars follow. */
  color-scheme: light;

  /* Categorical series. Each colour is paired with a dash pattern (see
     --series-N-dash) so series stay distinguishable in greyscale, in print
     and to a colour-blind reader. Brand blue leads. */
  --series-1: #3d7cc0;  --series-1-dash: none;
  --series-2: #e08561;  --series-2-dash: 7 4;
  --series-3: #1c7f56;  --series-3-dash: 2 3;
  --series-4: #8a5fbf;  --series-4-dash: 10 4 2 4;
  --series-5: #b7791f;  --series-5-dash: 4 3;
  --series-6: #0b7285;  --series-6-dash: 12 5;
  --series-7: #c0392b;  --series-7-dash: 3 3 8 3;
  --series-8: #5c6ac4;  --series-8-dash: 9 3;

  /* ONE radius. The only exceptions in the whole system are the 2px bars of
     the brand rule and the round dots of a spinner or status marker. The
     aliases all resolve to it so no component can drift. */
  --radius-sm: var(--radius-card);
  --radius: var(--radius-card);
  --radius-md: var(--radius-card);
  --radius-lg: var(--radius-card);
  --radius-pill: var(--radius-card);

  /* NO shadows. Kept as tokens purely so existing rules resolve to nothing
     rather than having to be hunted down one at a time. */
  --shadow-sm: none;
  --shadow-md: none;
  --shadow-lg: none;

  /* The guide's scale, in px. Sizes sit close together on purpose —
     nothing shouts. */
  --text-xs: 12px;    /* captions, the SNRGY attribution */
  --text-sm: 14px;    /* body — the workhorse */
  --text-base: 15px;  /* lead copy, labels */
  --text-lg: 17px;    /* section H2, card title */
  --text-xl: 24px;    /* standard page H1 */
  --text-2xl: 30px;   /* landing H1 */

  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
}

/* ==========================================================================
   1b. Dark theme
   --------------------------------------------------------------------------
   Seventeen values change, and that is all: the guide's sixteen, plus
   --color-unfav-strong for the reason given in the light block above. Salmon,
   gold, navy and the rest of the status ramp hold their exact values in both
   themes — they are the logo's colours and the reader's colours, and neither
   should shift with a preference. Otherwise only the pale status tints flip.

   The block appears TWICE because this is plain CSS: once under the device
   preference for users who never chose (guarded so an explicit
   data-theme="light" beats a dark OS), once under data-theme="dark" so the
   toggle beats a light OS. KEEP THE TWO COPIES IDENTICAL.
   ========================================================================== */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --color-surface: #131a29;
    --color-surface-sunken: #0d131f;
    --color-surface-raised: #1b2436;
    --color-border: #2a3549;
    --color-border-strong: #3c4a63;
    --color-text: #eef1f6;
    --color-text-muted: #a6b0c3;
    --color-text-subtle: #8590a6;
    --color-brand-blue: #6ba3dd;
    --color-brand-blue-dark: #8fbce8;
    --color-brand-blue-light: #1c2b40;
    --color-fav-light: #14301f;
    --color-unfav-light: #33211d;
    /* See the note in the light block: a rose-red that clears 4.5:1 on every
       dark ground it lands on (4.82:1 at worst, its own hover fill), where the
       guide's #c0392b reads 2.81:1. Deliberately rose rather than warmer — a
       lighter red drifts toward brand salmon, and a destructive control must
       never be mistakable for the jewellery. */
    --color-unfav-strong: #f25f6d;
    --color-neutral-light: #212b3d;
    --color-warn-bg: #2c2415;
    --color-warn-border: #5c4a1d;

    --btn-ink: #0b1b34;
    --brand-rgb: 107, 163, 221;
    --overlay-bg: rgba(13, 19, 31, 0.92);
    --scrim: rgba(0, 0, 0, 0.62);
    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --color-surface: #131a29;
  --color-surface-sunken: #0d131f;
  --color-surface-raised: #1b2436;
  --color-border: #2a3549;
  --color-border-strong: #3c4a63;
  --color-text: #eef1f6;
  --color-text-muted: #a6b0c3;
  --color-text-subtle: #8590a6;
  --color-brand-blue: #6ba3dd;
  --color-brand-blue-dark: #8fbce8;
  --color-brand-blue-light: #1c2b40;
  --color-fav-light: #14301f;
  --color-unfav-light: #33211d;
  /* Identical to the @media copy above, and for the same reason — keep the
     two in step. */
  --color-unfav-strong: #f25f6d;
  --color-neutral-light: #212b3d;
  --color-warn-bg: #2c2415;
  --color-warn-border: #5c4a1d;

  --btn-ink: #0b1b34;
  --brand-rgb: 107, 163, 221;
  --overlay-bg: rgba(13, 19, 31, 0.92);
  --scrim: rgba(0, 0, 0, 0.62);
  color-scheme: dark;
}

/* ==========================================================================
   2. Base
   --------------------------------------------------------------------------
   A quiet, high-contrast ground. The atmospheric background this system
   replaced — grain, line art, radial washes, drifting blobs — is gone on
   purpose: cards sit on the sunken layer and that is the whole depth model.
   ========================================================================== */

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

html {
  background-color: var(--page-bg);
  min-height: 100%;
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-optical-sizing: auto;
  font-size: var(--text-base);
  color: var(--ink);
  background-color: var(--page-bg);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* Focus is never removed. This ring is the accessibility floor of the
   system — if it looks wrong, fix the spacing, not the outline. No
   border-radius is set here: the outline already follows each element's own
   radius, and forcing one would reshape the element while it is focused. */
:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* --- The column ---------------------------------------------------------
   A narrow, centered, single-column product. Three widths, and that is the
   whole layout system — resist adding a fourth. */
.shell        { max-width: 480px; margin: 60px auto; padding: 0 20px; }
.shell--wide  { max-width: 760px; margin-top: 44px; }   /* work surfaces */
.shell--settings { max-width: 720px; }                  /* settings, tables */

/* ==========================================================================
   3. Typography
   ========================================================================== */

h1 { font-size: var(--text-xl); font-weight: 700; letter-spacing: -0.02em; color: var(--brand-ink); line-height: 1.2; }
h2, h3 { color: var(--brand-ink); }
h2 { font-size: var(--text-lg); font-weight: 600; }
h3 { font-size: var(--text-base); font-weight: 600; }

/* Tracked-caps section label — the utility voice of the type system. Used as
   an "eyebrow" over cards and groups. */
.overline {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
}
.muted { color: var(--muted); font-size: var(--text-sm); }
.subtle { color: var(--subtle); font-size: var(--text-xs); }

a { color: var(--brand); text-decoration: none; transition: color 0.15s ease; }
a:hover { color: var(--brand-dark); text-decoration: underline; }

/* Numeric data aligns only if the digits are the same width. Anything
   counting, timing or tabulating gets this. */
.tabular { font-variant-numeric: tabular-nums; }

/* ==========================================================================
   3b. Signature elements
   ========================================================================== */

/* The brand rule: four bars, salmon > gold > blue > navy, in that order.
   Sits under a page title, in place of a plain <hr>. This is the most
   recognisable Milieu element after the rings.

   In dark mode the navy bar sits very close to the surface and reads as a
   quiet terminator rather than a fourth stripe — expected, and why the order
   runs warm-to-dark rather than the reverse. */
.brand-rule {
  display: flex;
  gap: 3px;
  width: 72px;
  height: 4px;
  margin: 10px 0 0;
}
.brand-rule > span { flex: 1; border-radius: 2px; }
.brand-rule > span:nth-child(1) { background: var(--color-brand-salmon); }
.brand-rule > span:nth-child(2) { background: var(--color-brand-gold); }
.brand-rule > span:nth-child(3) { background: var(--color-brand-blue); }
.brand-rule > span:nth-child(4) { background: var(--color-brand-navy); }

/* The Milieu lockup. The word "Milieu" is LIVE TEXT, never part of the
   image: it inverts correctly in dark mode, stays crisp at any scale, and
   remains selectable and readable to a screen reader. The rings PNG
   contributes the mark and nothing else, at its own 1371:1262 aspect. */
/*
 * Everything is sized from one custom property, --lockup-h, the lockup's total
 * height. The proportions are the guide's: inline gives the mark the full
 * height and the wordmark 0.52 of it; stacked gives the mark 0.72 and the
 * wordmark 0.3. Driving it from a variable rather than inline pixel values is
 * what lets a media query shrink the whole object in one line.
 */
.lockup {
  --lockup-h: 40px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.lockup--stacked { flex-direction: column; align-items: flex-start; gap: 4px; }
.lockup img { display: block; width: auto; height: var(--lockup-h); }
.lockup--stacked img { height: calc(var(--lockup-h) * 0.72); }
.lockup__word { display: inline-flex; align-items: baseline; gap: 7px; }
.lockup__name {
  font-size: calc(var(--lockup-h) * 0.52);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.lockup__product {
  font-size: calc(var(--lockup-h) * 0.36);
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--muted);
  white-space: nowrap;
}
.lockup--stacked .lockup__name { font-size: calc(var(--lockup-h) * 0.3); }
.lockup--stacked .lockup__product { font-size: calc(var(--lockup-h) * 0.2); }

/* Powered by SNRGY — the canonical spec, and deliberately quiet. It credits
   the builder without competing with the organisation the software serves.
   Never reworded, never enlarged, never given brand blue, and the mark is
   always to the RIGHT of the text. */
.powered-by {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-xs);
  font-weight: 400;
  color: var(--subtle);
}
.powered-by img,
.powered-by svg { width: 14px; height: 14px; display: block; }

/* It belongs to the software, not to the document. */
@media print {
  .powered-by { display: none; }
}

/* ==========================================================================
   3c. Hover system — tone shift only, never motion.
   Lifts, slides and scale were removed on purpose: at scale they read as the
   page twitching under the cursor.
   ========================================================================== */

.hover-solid { transition: filter 0.12s ease; }
.hover-solid:hover { filter: brightness(0.94); }

.hover-surface { transition: background-color 0.12s ease, border-color 0.12s ease; }
.hover-surface:hover {
  background-color: var(--surface-2);
  border-color: var(--border-strong);
}

/* ==========================================================================
   4. Forms
   ========================================================================== */

form { display: flex; flex-direction: column; gap: 10px; margin-top: 16px; }
label { font-size: var(--text-base); font-weight: 500; }

input, select, textarea {
  min-height: 44px;
  padding: 0 14px;
  /* 16px or larger stops iOS zooming the page on focus. */
  font-size: 16px;
  font-family: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-card);
  transition: border-color 0.12s ease;
}
textarea { padding: 10px 14px; line-height: 1.6; }
input:hover, select:hover, textarea:hover { border-color: var(--border-strong); }
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-color: var(--brand);
}
/* Native tick boxes size themselves; the 44px floor is for text fields. */
input[type="checkbox"], input[type="radio"] { min-height: 0; }

/* Radio / checkbox option lists — quiet bordered rows instead of naked
   inputs, so a set of choices reads as a group. */
.choice-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; }
.choice {
  display: flex; align-items: baseline; gap: 9px;
  padding: 10px 12px;
  font-weight: 400; font-size: var(--text-base);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface);
  cursor: pointer;
  transition: background-color 0.12s ease, border-color 0.12s ease;
}
.choice:hover { border-color: var(--border-strong); background: var(--surface-2); }
.choice input { flex: none; width: auto; transform: translateY(1px); }

/* ==========================================================================
   5. Buttons
   --------------------------------------------------------------------------
   Primary is filled brand blue with a white 600-weight label and no border —
   one per view. Secondary is transparent with a border-strong outline.
   Destructive is OUTLINED IN RED AND NEVER FILLED: a filled red button
   invites the click it is warning about.

   Height is 46px for anything an end-user touches. Dense internal toolbars
   and icon buttons opt down by setting --btn-h on themselves.
   ========================================================================== */

button, .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--btn-h);
  padding: 0 18px;
  font-size: 16px;
  font-family: inherit;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  border: none;
  border-radius: var(--radius-card);
  background-color: var(--brand);
  background-image: none;
  color: var(--btn-ink);
  cursor: pointer;
  box-shadow: none;
  transition: filter 0.12s ease;
}
button:hover, .btn:hover {
  filter: brightness(0.94);
  text-decoration: none;
}
button:focus-visible, .btn:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
/* Disabled is opacity, never a grey repaint. */
button:disabled, .btn[aria-disabled="true"] {
  opacity: 0.6;
  cursor: default;
  filter: none;
}

/* Muted secondary action, sitting next to a primary. */
.btn-secondary {
  background: var(--btn-secondary-bg);
  color: var(--btn-secondary-ink);
  border: 1px solid var(--border-strong);
  transition: background-color 0.12s ease, border-color 0.12s ease;
}
.btn-secondary:hover { filter: none; background: var(--btn-secondary-hover); }

/* Destructive: outlined, never filled. */
.btn-danger {
  background: transparent;
  color: var(--danger);
  border: 1px solid var(--danger);
  transition: background-color 0.12s ease;
}
.btn-danger:hover { filter: none; background: var(--color-unfav-light); }

/* The "add another one" affordance: dashed, transparent, brand-coloured.
   Always additive, never destructive, never primary. */
.btn-add {
  --btn-h: 38px;
  width: auto; align-self: flex-start;
  background: transparent; color: var(--brand);
  border: 1px dashed var(--border-strong);
  font-size: var(--text-sm); padding: 0 14px;
  transition: background-color 0.12s ease, border-color 0.12s ease;
}
.btn-add:hover { filter: none; background: var(--brand-tint); border-color: var(--brand); }

/* Quiet backwards move — solid hairline rather than dashed, so it does not
   get mistaken for an "add". */
.btn-back {
  --btn-h: 38px;
  width: auto; padding: 0 14px; font-size: var(--text-sm);
  background: transparent; color: var(--brand);
  border: 1px solid var(--border-strong);
  transition: background-color 0.12s ease, border-color 0.12s ease;
}
.btn-back:hover { filter: none; background: var(--brand-tint); border-color: var(--brand); }

/* ==========================================================================
   6. Surfaces
   --------------------------------------------------------------------------
   A card is a 1px border, an 8px radius, and 16–20px of padding. Nothing
   else. There is no lift on hover and no shadow at any elevation.
   ========================================================================== */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  transition: background-color 0.12s ease, border-color 0.12s ease;
}
a.card, .card--link { color: inherit; text-decoration: none; display: block; }
a.card:hover, .card--link:hover {
  background: var(--surface-2);
  border-color: var(--border-strong);
  text-decoration: none;
}

/* Padded wrapper for forms and content blocks. */
.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 20px 22px;
}
.panel > h1:first-child, .panel > h2:first-child { margin-top: 0; }
.panel form { margin-top: 14px; }

/* Was glass over an atmospheric background; now simply the raised surface —
   still reserved for the one panel that is the whole point of its page. */
.panel--glass {
  background: var(--surface-3);
  border: 1px solid var(--border);
}

/* The mark on a header, at its own aspect ratio (1371:1262). The rings are
   three flat colours: never recoloured, outlined, rotated, given an effect,
   or cropped to a circle. */
.hero-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
}
.hero-mark img, .hero-mark svg {
  height: 100%;
  width: auto;
  display: block;
}

/* Icon tile — a rounded square of brand tint holding a 20–22px stroke icon
   or a single initial. The workhorse of every list row and settings card. */
.ic {
  flex: none;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  background: var(--brand-tint);
  color: var(--brand);
  border-radius: var(--radius-card);
  font-size: var(--text-lg); font-weight: 600;
}
.ic svg { width: 22px; height: 22px; }
.ic--sm { width: 40px; height: 40px; }
.ic--sm svg { width: 20px; height: 20px; }
.ic--success { background: var(--icon-good-bg); color: var(--icon-good-ink); }

/* Row: icon tile, text stack, chevron. Every navigational list item.
   Selector doubled up because `a.card` above sets display:block at two
   points of specificity — a bare `.row-link` loses to it and the row
   silently stacks. */
.row-link, a.card.row-link, .card.row-link {
  display: flex; align-items: center; gap: 14px; padding: 14px 18px;
}
.row-link .txt { flex: 1; min-width: 0; }
.row-link .txt strong { display: block; color: var(--brand-ink); }
.row-link .txt span { display: block; font-size: var(--text-sm); color: var(--muted); margin-top: 1px; }
.row-link .chev {
  flex: none; color: var(--subtle); font-size: 1.4rem; line-height: 1;
  transition: color 0.12s ease;
}
.row-link:hover .chev { color: var(--brand); }

/* Hub grid of cards. */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 14px;
  margin-top: 20px;
}

/* ==========================================================================
   7. Page header
   --------------------------------------------------------------------------
   Was a gradient hero in white text. It is now a plain surface: the greeting
   is content, and content sits on a card like everything else.
   ========================================================================== */

.hero {
  padding: 20px 22px;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface);
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: 18px;
}
.hero .hero-mark { height: 52px; }
.hero h1 { color: var(--brand-ink); margin: 0; }
.hero p { margin: 6px 0 0; color: var(--muted); font-size: var(--text-sm); }

/* Once the page has real work on it, the greeting steps back. */
.hero--compact { padding: 16px 20px; }
.hero--compact .hero-mark { height: 44px; }
.hero--compact p { margin-top: 3px; }

@media (max-width: 460px) {
  .hero { flex-direction: column; align-items: flex-start; gap: 12px; }
}

/* ==========================================================================
   8. Corner nav — one bordered object in the corner, not loose icons.
   ========================================================================== */

.corner-nav-bar {
  position: fixed;
  top: 12px; left: 14px;
  display: flex; align-items: center; gap: 4px;
  padding: 5px 7px;
  border-radius: var(--radius-card);
  background: var(--surface);
  border: 1px solid var(--border);
  z-index: 500;
}
.corner-nav-bar a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border-radius: var(--radius-card);
  color: var(--subtle);
  text-decoration: none;
  transition: color 0.12s ease, background-color 0.12s ease;
}
.corner-nav-bar a:hover { color: var(--brand); background: var(--brand-tint); text-decoration: none; }
.corner-nav-bar svg { width: 19px; height: 19px; display: block; }
/* The logo leads the bar, separated by a hairline so it registers as
   identity rather than a third destination. */
.corner-nav-bar .brand {
  width: auto; margin-right: 4px; padding-right: 8px;
  border-right: 1px solid var(--border); border-radius: 0;
}
.corner-nav-bar .brand img { height: 25px; width: auto; display: block; }
.corner-nav-bar .brand:hover { background: transparent; }

/* ==========================================================================
   9. Progress — the step rail and the bar
   ========================================================================== */

.steps { display: flex; list-style: none; margin: 0; padding: 0; }
.step { display: flex; align-items: center; flex: 1; }
.step:last-child { flex: 0; }
.step .dot {
  flex: none;
  width: 24px; height: 24px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 2px solid var(--border-strong);
  background: var(--surface);
  font-size: 11px; font-weight: 600;
  color: var(--muted);
  transition: background-color 0.25s ease, border-color 0.25s ease, color 0.25s ease;
}
.step .lbl {
  margin-left: 8px;
  font-size: var(--text-xs); font-weight: 600; letter-spacing: 0.02em;
  color: var(--muted);
  white-space: nowrap;
  transition: color 0.25s ease;
}
.step .line {
  flex: 1; height: 2px; margin: 0 10px;
  border-radius: 1px; background: var(--color-neutral-light);
  position: relative; overflow: hidden;
}
.step .line::after {
  content: "";
  position: absolute; inset: 0;
  background: var(--brand);
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.4s var(--ease);
}
.step.done .line::after { transform: scaleX(1); }
.step.done .dot { background: var(--brand); border-color: var(--brand); color: var(--btn-ink); }
.step.active .dot { border-color: var(--brand); color: var(--brand); }
.step.done .lbl, .step.active .lbl { color: var(--brand-ink); }

/* An empty track is inert fill, not a tinted brand colour. */
.progress-track {
  width: min(320px, 100%); height: 8px;
  background: var(--color-neutral-light);
  border-radius: var(--radius-card); overflow: hidden;
}
.progress-fill {
  height: 100%; width: 0%;
  background: var(--brand);
  border-radius: var(--radius-card);
  transition: width 0.3s ease-out;
}

.spinner {
  width: 40px; height: 40px;
  border: 3px solid var(--border-strong);
  border-top-color: var(--brand);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
.spinner--sm { width: 10px; height: 10px; border-width: 2px; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Full-screen busy state. Near-opaque rather than frosted — there is no
   backdrop-filter anywhere in this system. */
.overlay-busy {
  position: fixed; inset: 0;
  display: none;
  background: var(--overlay-bg);
  z-index: 1000;
  align-items: center; justify-content: center; flex-direction: column; gap: 14px;
}
.overlay-busy.visible { display: flex; }

/* ==========================================================================
   10. Status
   --------------------------------------------------------------------------
   Status colours are deliberately not brand colours, and colour is never the
   only carrier of meaning — pair every signal with a glyph or a label.
   ========================================================================== */

.alert {
  padding: 10px 14px;
  border-radius: var(--radius-card);
  font-size: var(--text-base);
  border: 1px solid;
}
.alert-error   { background: var(--error-bg);   border-color: var(--error-border);   color: var(--error-ink); }
.alert-success { background: var(--success-bg); border-color: var(--success-border); color: var(--success-ink); }
.alert-warn    { background: var(--warn-bg);    border-color: var(--warn-border);    color: var(--warn-ink); }

.pill {
  display: inline-block;
  padding: 2px 9px;
  border-radius: var(--radius-card);
  font-size: var(--text-xs);
  font-weight: 600;
}
.pill-brand   { background: var(--brand-tint);  color: var(--brand-dark); }
.pill-success { background: var(--success-bg);  color: var(--success-ink); }
.pill-warn    { background: var(--warn-bg);     color: var(--warn-ink); }
.pill-error   { background: var(--error-bg);    color: var(--error-ink); }

/* An outcome, one per line: tinted row, coloured border, a dot that carries
   the state at a glance. */
.result-item {
  display: flex; gap: 10px; align-items: baseline;
  padding: 12px 14px;
  border-radius: var(--radius-card);
  border: 1px solid;
}
.result-item .dot { flex: none; width: 9px; height: 9px; border-radius: 50%; transform: translateY(-1px); }
.result-saved  { background: var(--success-bg); border-color: var(--success-border); }
.result-saved .dot { background: var(--color-fav); }
.result-warn   { background: var(--warn-bg);    border-color: var(--warn-border); }
.result-warn .dot { background: var(--color-warn); }
.result-failed { background: var(--error-bg);   border-color: var(--error-border); }
.result-failed .dot { background: var(--color-unfav-strong); }

/* ==========================================================================
   11. Motion
   --------------------------------------------------------------------------
   There is almost none. Entrance reveals and hover lifts were removed on
   purpose — nothing moves unless the user moved it. What remains is tone,
   and the login→home transition, which is decoration and disables itself
   under the query below.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
