/* EnergyMark design system.
   Implements "EnergyMark Bid App Design Guidelines" (claude.ai/design project
   2bf72eb4-dec3-4c33-aaf9-bac7563fe10b), read 09/15/2026.

   THREE IDEAS FROM THE GUIDELINES THAT SHAPE EVERYTHING BELOW.

   1. Colour inside a data view only ever means something. The brand's green and cyan carry
      the identity on the public site, where nothing means anything. In the product they are
      declared as --identity-* OUTSIDE the semantic set, so reaching for one in a data view
      looks wrong in review. --good moved from the brand green to a teal precisely so the two
      can never be confused.

   2. There are FOUR states, not three. Undecidable is not a problem to fix and not a danger
      to avoid; it is an honest answer that routes to a human. Violet, dashed, never a solid
      fill, so it reads as neither traffic light nor brand.

   3. The Montserrat boundary. Montserrat is the display side: headings, the wordmark,
      buttons, sign-in, and customer prose. The system stack is the data side: every table
      cell, rate, date, account number and field name. Montserrat has no tabular figures, so
      a column of numbers set in it jitters. A row in a table is never Montserrat; a heading
      above it always is.

   FONT LOADING. Self-hosted woff2 with font-display:swap, and the shells preload the latin
   file. No third-party request on any page: the earlier Google Fonts link meant every page
   load told Google who was reading an energy bill, and an @import before that blocked
   rendering outright.
*/


/* Self-hosted, per the guidelines. Two facts made this cheaper than expected:

   1. Google now ships Montserrat as a VARIABLE font, so the 500, 600 and 700 URLs return
      identical bytes. One file per subset covers the whole weight range: 106 KB, not 318.
   2. Splitting latin from latin-ext means a browser only fetches the accented subset when a
      page actually contains one. Quebec bills carry accents, so latin-ext has to exist, but
      most pages never touch it.

   font-display: swap so text paints immediately in the fallback stack and reflows when the
   face lands. Nothing waits on a webfont.
*/
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url('fonts/montserrat-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url('fonts/montserrat-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* ---- semantic: these mean something ------------------------------------------------ */
  /* Taken from the public landing page so the click from front door to sign-in does not
     change colour under someone. It is also the better value: 8.30 against the old 7.18. */
  --brand:      #1a4f8a;   /* 8.30 on white, AAA. Structure, links, actions. Never a state. */
  /* The landing page's hero and footer, so the bar above a signed-in customer is the same
     dark they just scrolled past rather than a near-miss of it. */
  --brand-dark:  #03427a;  /* 10.17 AAA. Dark surfaces: the nav, panels, the footer.        */
  --brand-hover: #133a67;  /* 11.48 AAA. The landing's own link hover.                      */
  --brand-wash: #eef4fb;   /* the landing's own ghost-hover wash                           */

  --ink:   #1c313c;        /* 13.51 AAA */
  --ink-2: #3c4a58;
  --ink-3: #6b7a89;

  --good:       #0f766e;   /* moved bluer, away from the brand green, so the two cannot be */
  --good-wash:  #ecf8f6;   /* confused. Complete, verified, awarded.                       */
  --warn:       #a85f00;   /* unchanged. Amber is far enough from the brand green.         */
  --warn-wash:  #fdf5e9;   /* Time pressure, drifting, near a limit.                       */
  --bad:        #b3261e;   /* Failed, expired, rejected. A missing input is NOT bad.       */
  --bad-wash:   #fdeeed;
  --unknown:      #5b4d9c; /* the fourth state. Outside the traffic light and outside the  */
  --unknown-wash: #f3f1fb; /* brand, so it reads as neither.                               */

  /* ---- identity: these mean nothing, and may never carry state ----------------------- */
  /* EnergyMark green, promoted from a logo colour to the accent the landing page runs on.
     THREE TONES, because one cannot do the job: at 3.52 the brand green is bright enough
     for a rule or a bullet and nowhere near the 4.5 a piece of text needs. Using the fill
     tone for a button label is the mistake this split exists to make impossible.

     THE COLLISION TO KEEP IN MIND. --good is a teal-green, and green is now also the brand
     accent, so green alone no longer distinguishes "this succeeded" from "this is us". That
     is survivable only because every state in this system already carries a second signal:
     a tick, a cross, a dashed rule. If a state is ever reduced to colour alone, this is the
     pair that breaks first. */
  --accent:      #1d7a35;      /* 5.40 AA. Text, button labels, anything readable.         */
  --accent-fill: #2e9c4a;      /* 3.52. Rules, bullets, large fills. NEVER carries text.   */
  --accent-soft: #7fd199;      /* 9.00 against dark ink. Labels and fills on dark panels.  */
  --identity-green: var(--accent-fill);   /* the old name, kept so nothing has to move      */
  --identity-cyan:  #09a6e0;   /* 2.78 contrast: never eligible as a text colour anywhere. */

  /* Both retuned to the values in the customer app design, which is now the reference for
     the signed-in side. The old pair were half a step darker and made every card edge read
     heavier than the design intends. */
  --line:   #e2e7ec;
  --line-2: #eef1f4;
  --paper:  #ffffff;
  --ground: #f6f8fa;
  --hover:  #f9fbfc;   /* row and panel hover                                             */

  /* Chip fills. Each state pairs a wash with a border a shade stronger, so a chip reads as
     a chip at a glance and still carries its mark for anyone who cannot see the colour. */
  --good-chip:  #f0f7f6;  --good-edge:  #bcdbd8;
  --warn-chip:  #fdf6ec;  --warn-edge:  #e8d3ad;
  --ghost-edge: #cdd6df;  /* secondary button outline                                     */

  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px;

  --r: 6px;        /* desk */
  --r-lg: 10px;    /* customer */
  /* One shadow in the system, for overlays only. Cards, tables and rows separate by rules,
     never by lift. Nothing in the desk shell casts a shadow. */
  --shadow-overlay: 0 8px 28px rgba(28,49,60,.16);

  --display: "Montserrat", "Segoe UI", system-ui, sans-serif;
  --data: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial,
          sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

/* Desk shell: the data side. 15px base, system stack, tabular figures everywhere. */
body {
  margin: 0;
  font-family: var(--data);
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink);
  background: var(--ground);
  font-variant-numeric: tabular-nums;
  scrollbar-gutter: stable;
}

/* Headings are the display side at both densities. */
h1, h2, h3 { font-family: var(--display); line-height: 1.22; margin: 0 0 var(--s2);
             letter-spacing: -.012em; }
h1 { font-size: 22px; font-weight: 700; }
h2 { font-size: 16px; font-weight: 600; margin-top: var(--s6); }
h3 { font-size: 14px; font-weight: 600; }
p  { margin: 0 0 var(--s3); }

a { color: var(--brand);
    text-decoration-color: color-mix(in srgb, var(--brand) 32%, transparent);
    text-underline-offset: 2px; }
a:hover { color: var(--brand-hover); text-decoration-color: currentColor; }

/* Never removed, never a colour change alone, visible on every surface. */
:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.nav :focus-visible { outline-color: #fff; }

.muted  { color: var(--ink-3); }
.small  { font-size: 12px; }
.tiny   { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; }
.num    { text-align: right; font-variant-numeric: tabular-nums; }
.mono   { font-family: var(--mono); font-size: 11px; }
.nowrap { white-space: nowrap; }
.strong { font-weight: 600; }
.display { font-family: var(--display); }

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

.nav {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s5);
  padding: 0 var(--s6); min-height: 52px;
  background: var(--brand-dark); color: #cfe0f0; font-size: 13px;
  /* The one brand moment in the desk shell: a 6px identity rule, carrying no state. */
  border-bottom: 6px solid var(--identity-green);
}
.nav a { color: #fff; text-decoration: none; padding: 2px 0;
         border-bottom: 2px solid transparent; }
.nav a:hover { color: #fff; border-bottom-color: rgba(255,255,255,.45); }
.nav .brand { font-family: var(--display); font-weight: 700; font-size: 15px;
              letter-spacing: .01em; margin-right: var(--s3); }
.nav .brand a { border: 0; }
.nav .grow { flex: 1; }
.nav .who { color: #a9c3dc; font-size: 12px; }
.badge-count { background: var(--bad); color: #fff; border-radius: 99px;
               padding: 0 6px; font-size: 11px; margin-left: 3px; }

.page      { max-width: 74rem; margin: var(--s5) auto var(--s7); padding: 0 var(--s6); }
.page-slim { max-width: 46rem; }
.page-mid  { max-width: 58rem; }
.lede { color: var(--ink-2); margin: -2px 0 var(--s5); }

/* ---- surfaces: rules, never lift ---------------------------------------------------- */

.card {
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r);
  padding: var(--s4); margin-bottom: var(--s4);
}
.card > :first-child { margin-top: 0; }
.card > :last-child  { margin-bottom: 0; }
.card h2 { margin-top: 0; }

.grid   { display: grid; gap: var(--s4); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }

/* ---- the four states ---------------------------------------------------------------- */

/* A chip always carries a WORD. State is never colour alone. */
.chip {
  display: inline-flex; align-items: baseline; gap: 5px;
  padding: 2px 8px; border-radius: 99px; font-size: 12px; font-weight: 600;
  background: var(--line-2); color: var(--ink-2); font-family: var(--data);
}
.chip::before { font-weight: 700; }
.chip.good    { background: var(--good-wash); color: var(--good); }
.chip.good::before { content: "\2713"; }
.chip.warn    { background: var(--warn-wash); color: var(--warn); }
.chip.warn::before { content: "!"; }
.chip.bad     { background: var(--bad-wash);  color: var(--bad); }
.chip.bad::before  { content: "\2717"; }
/* Never a solid fill. The dashed rule is the second signal: the line is open because the
   answer is open. Keeps it subordinate to the other three while still unmissable. */
.chip.unknown { background: var(--unknown-wash); color: var(--unknown);
                border: 1px dashed var(--unknown); }
.chip.unknown::before { content: "?"; }

/* .pill is the older name for the same thing; kept so existing screens do not regress. */
.pill { display: inline-block; padding: 1px 8px; border-radius: 99px; font-size: 12px;
        font-weight: 600; background: var(--line-2); color: var(--ink-2); }
.pill.good { background: var(--good-wash); color: var(--good); }
.pill.warn { background: var(--warn-wash); color: var(--warn); }
.pill.bad  { background: var(--bad-wash);  color: var(--bad); }
.pill.unknown { background: var(--unknown-wash); color: var(--unknown);
                border: 1px dashed var(--unknown); }

/* An undecidable note has four parts, always in this order: the label, the plain English
   reason, what would settle it, who holds it now. Never an icon alone, never a bare dash in
   a cell, and no retry button, because nothing here is a transient failure. */
.undecidable {
  border: 1px dashed var(--unknown); background: var(--unknown-wash);
  border-radius: var(--r); padding: var(--s3) var(--s4); margin-bottom: var(--s4);
}
.undecidable > :last-child { margin-bottom: 0; }
.undecidable .what-settles,
.undecidable .who-holds { font-size: 12px; color: var(--ink-2); margin-bottom: var(--s1); }
.undecidable .what-settles b,
.undecidable .who-holds b { font-weight: 600; color: var(--ink); }

.note { border-left: 3px solid var(--brand); background: var(--brand-wash);
        padding: var(--s3) var(--s4); border-radius: 0 var(--r) var(--r) 0;
        margin-bottom: var(--s4); }
.note.good { border-color: var(--good); background: var(--good-wash); }
.note.warn { border-color: var(--warn); background: var(--warn-wash); }
.note.bad  { border-color: var(--bad);  background: var(--bad-wash); }
.note.unknown { border: 1px dashed var(--unknown); border-left-width: 3px;
                background: var(--unknown-wash); border-radius: var(--r); }
.note :last-child { margin-bottom: 0; }

/* ---- tables: the data side ---------------------------------------------------------- */

.table-wrap { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-family: var(--data); font-size: 13px;
        font-variant-numeric: tabular-nums; }
th, td { text-align: left; padding: 6px var(--s4) 6px 0; vertical-align: top; }
thead th { font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
           color: var(--ink-3); font-weight: 600; border-bottom: 1px solid var(--line);
           padding-bottom: var(--s2); white-space: nowrap; }
/* 1px rules only, no zebra striping, so state washes are the only fill on the screen. */
tbody tr { border-bottom: 1px solid var(--line-2); }
tbody tr:last-child { border-bottom: 0; }
tr.quiet td  { color: var(--ink-3); }
tr.struck td { text-decoration: line-through; color: var(--ink-3); }

dl.facts { display: grid; grid-template-columns: minmax(8rem, 13rem) 1fr;
           gap: var(--s2) var(--s4); margin: 0 0 var(--s4); }
dl.facts dt { color: var(--ink-3); font-size: 12px; }
dl.facts dd { margin: 0; }

/* ---- confidence: a quantity, drawn not coloured ------------------------------------- */

/* Confidence (how sure the extraction is) and flagged (whether a cross-check failed) are
   separate axes and must never collapse into one ramp: a HIGH confidence field that fails a
   cross-check is the single most important thing on the screen. Flagged owns the tint so
   confidence can stay neutral. */
.ticks { display: inline-flex; gap: 2px; vertical-align: middle; }
.ticks i { width: 4px; height: 14px; border-radius: 1px; background: var(--line);
           display: block; }
.ticks i.on { background: var(--ink-2); }

tr.flagged td { background: var(--bad-wash); }
tr.flagged .flag { color: var(--bad); font-weight: 700; }
/* Low confidence with no flag is the extraction declining to assert, which is undecidable. */
tr.band-low:not(.flagged) td { background: var(--unknown-wash); }

/* ---- forms -------------------------------------------------------------------------- */

label { display: block; font-size: 12px; font-weight: 600; margin-bottom: var(--s1);
        color: var(--ink-2); }
input[type=text], input[type=email], input[type=password], input[type=number],
input[type=search], input[type=date], input[type=datetime-local], input[type=file],
select, textarea {
  width: 100%; font-family: var(--data); font-size: 13px; color: var(--ink);
  font-variant-numeric: tabular-nums;
  padding: 7px 9px; background: var(--paper);
  border: 1px solid var(--line); border-radius: var(--r); min-height: 32px;
}
input:focus-visible, select:focus-visible, textarea:focus-visible { border-color: var(--brand); }
input[type=checkbox], input[type=radio] { width: auto; min-height: 0;
                                          accent-color: var(--brand); }
textarea { min-height: 72px; resize: vertical; }

form p { margin: 0 0 var(--s3); }
.helptext { display: block; color: var(--ink-3); font-size: 12px; margin-top: var(--s1);
            font-weight: 400; }
span.helptext { display: block; }
ul.errorlist { margin: 0 0 var(--s1); padding-left: 1.1rem; color: var(--bad);
               font-size: 12px; }

/* Buttons are the display side. 32px target in the desk shell, 44px in the customer shell. */
.btn { display: inline-flex; align-items: center; justify-content: center;
       font-family: var(--display); font-size: 13px; font-weight: 600;
       min-height: 32px; padding: 6px 14px; border-radius: var(--r);
       border: 1px solid transparent; background: var(--accent); color: #fff;
       cursor: pointer; text-decoration: none; }
.btn:hover { background: #16602a; color: #fff; }
.btn:disabled, .btn.disabled { background: #9fb0bf; cursor: not-allowed; }
.btn.ghost  { background: var(--paper); color: var(--ink); border-color: var(--line); }
.btn.ghost:hover { background: var(--line-2); color: var(--ink); }
/* GREEN MEANS ACT, BLUE MEANS NAVIGATE. The landing page's call to action is green, so a
   customer who clicks it and arrives at a blue button has been handed a different product.
   Blue keeps links, chrome and structure; green is now the thing you press, on both sides
   of the sign-in.

   .go is deliberately no longer a separate colour. It existed to mark the confirming action
   on a screen full of blue buttons, and on a screen where the primary action is already
   green a second, adjacent green says nothing and reads as a mistake. The state colours
   (--good and the rest) stay where they belong, on chips and status, never on a button. */
.btn.go     { background: var(--accent); } .btn.go:hover { background: #16602a; }
.btn.danger { background: var(--paper); color: var(--bad); border-color: #e7c3c0; }
.btn.small  { min-height: 28px; padding: 3px 10px; font-size: 12px; }
.btn-link   { background: none; border: 0; padding: 0; font: inherit; font-size: 12px;
              color: var(--brand); text-decoration: underline; cursor: pointer; }
.actions { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap;
           margin-top: var(--s4); }

/* ---- figures ------------------------------------------------------------------------ */

.figure    { font-family: var(--data); font-variant-numeric: tabular-nums;
             font-size: 19px; font-weight: 700; line-height: 1.15; }
.figure-lg { font-family: var(--data); font-variant-numeric: tabular-nums;
             font-size: 28px; font-weight: 700; line-height: 1.1; letter-spacing: -.015em; }
.figure-sm { font-family: var(--data); font-variant-numeric: tabular-nums;
             font-size: 16px; font-weight: 600; }
.caption { color: var(--ink-3); font-size: 12px; margin-top: 2px; }
.price { font-weight: 600; font-variant-numeric: tabular-nums; }

/* ---- both shells: same tokens, same components, different density ------------------- */

/* These were the pre-design customer overrides. They are gone rather than retuned: every one
   of them now conflicts with the shared component layer at the foot of this file, and a
   two-class selector beats a one-class one, so leaving them meant the design was written and
   then quietly overruled. Anything still needed below is stated there once, for both shells. */

.app-shell { font-family: var(--display); font-size: 14px; font-weight: 500; }
.app-shell .lede { font-size: 15px; }
.app-shell input, .app-shell select, .app-shell textarea { min-height: 40px; font-size: 14px; }
/* Figures and anything that has to line up stay on the data stack: Montserrat has no
   tabular figures, so a column set in it jitters. */
.app-shell .figure, .app-shell .figure-lg, .app-shell .figure-sm,
.app-shell .num, .app-shell .mono, .app-shell td { font-family: var(--data); }

/* ---- components --------------------------------------------------------------------- */

.cards, .doors { display: grid; gap: var(--s4);
                 grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
                 align-items: start; }
.card.urgent { border-left: 3px solid var(--bad); }
.card.warn   { border-left: 3px solid var(--warn); }
.card.calm   { border-left: 3px solid var(--good); }
.card.offer  { border-left: 3px solid var(--good); }
.card.live   { border-left: 3px solid var(--good); }
.card.calm .figure { color: var(--good); }
.card.urgent .figure { color: var(--bad); }

ul.items { list-style: none; padding: 0; margin: var(--s3) 0 0; }
ul.items li { padding: 5px 0; border-top: 1px solid var(--line-2); font-size: 13px; }
ul.items li:first-child { border-top: 0; }

.next { border-left: 3px solid var(--brand); background: var(--brand-wash);
        padding: var(--s3) var(--s4); border-radius: 0 var(--r) var(--r) 0;
        margin: var(--s4) 0 var(--s5); }

tr.expired td, tr.retired td, tr.declined td { color: var(--ink-3); }
tr.retired td { text-decoration: line-through; }
tr.best { font-weight: 600; }          /* weight and a blue label, never a hue */
tr.current { font-weight: 600; }

.pass { color: var(--good); }
.fail { color: var(--bad); font-weight: 600; }

.arith { font-family: var(--mono); font-size: 14px; }
.mine, .won, .awarded { border-left: 3px solid var(--good); background: var(--good-wash);
                        padding: var(--s3) var(--s4); border-radius: 0 var(--r) var(--r) 0;
                        margin-bottom: var(--s4); }
.stale { border-left: 3px solid var(--warn); background: var(--warn-wash);
         padding: var(--s3) var(--s4); border-radius: 0 var(--r) var(--r) 0;
         margin-bottom: var(--s4); }
.answered { color: var(--good); font-size: 12px; }
.preview { border: 1px solid var(--line); background: var(--line-2);
           border-radius: var(--r); padding: var(--s4); margin: var(--s4) 0; }
.notes { margin: var(--s4) 0; }

form.search { display: flex; gap: var(--s2); align-items: center; margin-bottom: var(--s5); }
form.search input[type=search] { max-width: 26rem; }
form.create, form.bid, form.override {
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r);
  padding: var(--s4); margin: var(--s5) 0;
}
.app-shell form.bid { border-radius: var(--r-lg); padding: var(--s5); }

label.acct { display: flex; gap: var(--s2); align-items: baseline; font-weight: 400;
             font-size: inherit; padding: var(--s2) 0;
             border-bottom: 1px solid var(--line-2); }
label.acct:last-of-type { border-bottom: 0; }

table.range td { padding: 2px var(--s4) 2px 0; border: 0; }

button:not(.btn):not(.btn-link) {
  font-family: var(--display); font-size: 13px; font-weight: 600; min-height: 32px;
  padding: 6px 14px; border-radius: var(--r); border: 1px solid var(--line);
  background: var(--paper); color: var(--ink); cursor: pointer;
}
button:not(.btn):not(.btn-link):hover { background: var(--line-2); }

.empty-state { border: 1px dashed var(--line); border-radius: var(--r);
               padding: var(--s5); background: var(--paper); }
.empty-state .strong { font-size: 15px; margin-bottom: var(--s2); }
.empty-state .actions { margin-top: var(--s4); }
.empty { color: var(--ink-3); font-size: 13px; padding: var(--s3) 0; }

/* ---- bill review: the one bespoke layout -------------------------------------------- */

.split { display: flex; gap: var(--s5); align-items: flex-start; }
.split .pane { flex: 1 1 50%; min-width: 0; }
.split .viewer { position: sticky; top: 0; max-height: 100vh; overflow: auto;
                 background: var(--line-2); border-radius: var(--r); padding: var(--s3); }
.split .viewer img { display: block; width: 100%; cursor: zoom-in; border-radius: 3px; }
.split .viewer img.zoomed { width: auto; max-width: none; cursor: zoom-out; }
/* Never side by side under 1100px. */
@media (max-width: 1100px) {
  .split { flex-direction: column; }
  .split .viewer { position: static; max-height: 34rem; }
}

.stack > * + * { margin-top: var(--s3); }
.row { display: flex; gap: var(--s3); align-items: baseline; flex-wrap: wrap; }
.divider { border: 0; border-top: 1px solid var(--line); margin: var(--s5) 0; }
@media print { .noprint { display: none; } body { background: #fff; } }

@media (max-width: 40rem) {
  .page { padding: 0 var(--s4); margin-top: var(--s4); }
  .app-shell .page { padding: 0 var(--s4); margin-top: var(--s5); }
  .nav { padding: var(--s3) var(--s4); gap: var(--s2) var(--s4); }
  .app-shell h1 { font-size: 28px; }
  .app-shell h2 { font-size: 19px; }
  dl.facts { grid-template-columns: 1fr; gap: 0; }
  dl.facts dt { margin-top: var(--s3); }
  .figure-lg { font-size: 24px; }
  .figure { font-size: 17px; }

  /* A table scrolls ITSELF rather than the page. One rule instead of wrapping eleven
     tables by hand, and it cannot be forgotten on the next one somebody adds. Only at
     phone width: at desk width a table that needs a scrollbar is a layout problem to fix,
     not to hide. */
  table { display: block; overflow-x: auto; white-space: nowrap;
          -webkit-overflow-scrolling: touch; }
  table thead, table tbody, table tr { display: table; width: 100%;
                                       table-layout: auto; }

  /* Emails, account numbers and storage keys are long and unbreakable, and a single one of
     them sets the width of the whole page. */
  td, dd, .mono, .muted, li { overflow-wrap: anywhere; }

  /* Every target reaches 44px on a phone regardless of shell, because a thumb is a thumb. */
  .btn, button, input, select, textarea { min-height: 44px; }
  .btn.small { min-height: 36px; }
  .actions { gap: var(--s3); }
  .actions .btn { flex: 1 1 auto; justify-content: center; }

  .cards, .doors, .grid-2, .grid-3 { grid-template-columns: 1fr; }
  .blocker { grid-template-columns: 1fr; }
  .blocker-mark { text-align: left; }
  form.search { flex-wrap: wrap; }
  form.search input[type=search] { max-width: none; }
  .rangebar-scale { font-size: 11px; }
}

/* ---- price with expiry (component 6) ------------------------------------------------ */

.price-block { border: 1px solid var(--line); border-radius: var(--r); padding: var(--s4);
               margin-bottom: var(--s4); }
.app-shell .price-block { border-radius: var(--r-lg); padding: var(--s5);
                          background: var(--brand-wash); border-color: transparent; }
.price-block .per { font-size: .55em; font-weight: 500; color: var(--ink-2); }
/* The figure changes colour only in the warn and expired states. A live price is ink,
   because it is a price and not good news. Never green. */
.price-block .figure-lg.is-warn { color: var(--warn); }
.price-block .figure-lg.is-expired { color: var(--bad); text-decoration: line-through; }
.price-block .decay { height: 4px; background: var(--line-2); border-radius: 99px;
                      overflow: hidden; margin: var(--s3) 0 var(--s2); }
.price-block .decay i { display: block; height: 100%; background: var(--ink-3); }
.price-block.good .decay i { background: var(--good); }
.price-block.warn .decay i { background: var(--warn); }
.price-block.bad  .decay i { background: var(--bad); }
.price-block .expiry-line { display: flex; gap: var(--s2); align-items: baseline;
                            flex-wrap: wrap; margin-bottom: var(--s2); }

/* "Critical" marks a field whose value must be right; it is not a FAILURE, so it may not
   wear --bad. Bad is reserved for finished failure, and a field that simply matters has not
   failed. Weight and a rule carry it instead of a hue. */
.critical-mark { color: var(--ink-2); font-weight: 700; border-bottom: 2px solid var(--ink-3);
                 padding-bottom: 1px; }

/* ---- the blocker list (component 4) -------------------------------------------------- */

.blockers { margin-bottom: var(--s6); }
/* The only heading on the desk home over 16px. */
.blockers-head { font-size: 20px; margin-top: 0; }
.blocker {
  display: grid; grid-template-columns: 22px 1fr auto; gap: var(--s3);
  align-items: start; padding: var(--s3) var(--s4); margin-bottom: var(--s2);
  border-radius: var(--r);
  /* The row wash IS the state. Undecidable rows are the common case and are not failures. */
  border: 1px dashed var(--unknown); background: var(--unknown-wash);
}
.blocker.warn { border: 1px solid var(--warn); background: var(--warn-wash); }
.blocker.bad  { border: 1px solid var(--bad);  background: var(--bad-wash); }
/* Empty is a strip, not an absence: a cleared list and a missing list must not look alike. */
.blocker.clear { border: 1px solid var(--line); background: var(--paper); min-height: 56px;
                 align-items: center; }
.blocker-mark { font-weight: 700; font-size: 15px; text-align: center; color: var(--unknown); }
.blocker.warn .blocker-mark { color: var(--warn); }
.blocker.clear .blocker-mark { color: var(--good); }
.blocker-truth { font-weight: 600; margin-bottom: 2px; }
.blocker-clears { color: var(--ink-2); margin-bottom: 0; }
.blocker p:last-child { margin-bottom: 0; }
@media (max-width: 40rem) { .blocker { grid-template-columns: 22px 1fr; }
                            .blocker .btn { grid-column: 2; justify-self: start; } }

/* ---- rate position (component 3) ---------------------------------------------------- */

/* The customer's own rate stays at body size, in ink, inside a sentence. Never a hero
   figure, never green, never with a delta beside it. */
.num-inline { font-family: var(--data); font-variant-numeric: tabular-nums; }
.position { margin-bottom: var(--s5); }
.rangebar { position: relative; height: 10px; margin: var(--s1) 0 var(--s1); }
.rangebar .span { position: absolute; inset: 3px 0; border-radius: 99px;
                  background: var(--brand); opacity: .28; }
.rangebar.yours .span { opacity: .45; }
/* Ink tick for the customer. Not a colour, not an arrow: it marks a position, nothing more. */
.rangebar .tick { position: absolute; top: -2px; width: 2px; height: 14px;
                  background: var(--ink); transform: translateX(-1px); }
.rangebar-scale { display: flex; justify-content: space-between; gap: var(--s3);
                  margin-bottom: var(--s4); }
.rangebar-scale .you { color: var(--ink); font-weight: 600; }

/* ---- the RFP card (component 5) ----------------------------------------------------- */

/* The anonymised and awarded cards share a layout so the change reads AS a change: the
   header wash goes grey to good, and the identity block appears above everything. */
.rfp-head { border: 1px solid var(--line); border-left: 3px solid var(--ink-3);
            background: var(--line-2); border-radius: var(--r);
            padding: var(--s3) var(--s4); margin-bottom: var(--s4); }
.rfp-head.awarded { border-color: var(--good); border-left-color: var(--good);
                    background: var(--good-wash); }

/* Twelve bars, no axis. Suppliers read shape; the values are in the grid above. */
.sparkline { display: flex; align-items: flex-end; gap: 3px; height: 40px; }
.sparkline i { flex: 1; background: var(--brand); opacity: .55; border-radius: 1px 1px 0 0;
               min-height: 2px; }

/* ---- the enrolment file (Section 5.2's human gate) ---------------------------------- */

.filecheck { display: grid; grid-template-columns: 22px 1fr; gap: var(--s3);
             align-items: start; padding: var(--s3) var(--s4); border-radius: var(--r);
             border: 1px solid var(--line); background: var(--paper); }
.filecheck.met { border-left: 3px solid var(--good); }
.filecheck.missing { border-left: 3px solid var(--bad); background: var(--bad-wash); }
/* Undecidable keeps the dashed rule: the package waits on a person, it has not failed. */
.filecheck.undecidable { border: 1px dashed var(--unknown); background: var(--unknown-wash); }
.filecheck-mark { font-weight: 700; text-align: center; color: var(--ink-3); }
.filecheck.met .filecheck-mark { color: var(--good); }
.filecheck.missing .filecheck-mark { color: var(--bad); }
.filecheck.undecidable .filecheck-mark { color: var(--unknown); }

/* Switch tracker (Section 4.5). A stage not reached is drawn faint rather than hidden: the
   customer needs the whole road, not only the part behind them. The connecting rule is the
   point of the component, so it is a real border rather than spacing that implies one. */
.track { list-style: none; margin: var(--s4) 0; padding: 0; }
.track-step { display: grid; grid-template-columns: 22px 1fr; gap: var(--s3);
              align-items: start; padding: 0 0 var(--s4) var(--s3);
              border-left: 2px solid var(--line); margin-left: 10px; }
.track-step:last-child { border-left-color: transparent; padding-bottom: 0; }
.track-mark { font-weight: 700; text-align: center; color: var(--ink-3);
              margin-left: calc(-1 * var(--s3) - 12px); background: var(--paper); }
.track-step.done .track-mark { color: var(--good); }
.track-step.now .track-mark { color: var(--ink); }
.track-step.stopped .track-mark { color: var(--bad); }
/* Not yet reached, so it is quiet rather than absent. */
.track-step.later { color: var(--ink-3); }
.track-step.later .strong { font-weight: 500; }

/* Customer navigation. The current section is marked by an underline rather than by colour
   alone, so it survives greyscale and colour blindness like every other state in here. */
.navlink { color: #fff; opacity: .78; text-decoration: none; padding: var(--s2) var(--s3);
           border-bottom: 2px solid transparent; }
.navlink:hover { opacity: 1; }
.navlink.on { opacity: 1; border-bottom-color: #fff; font-weight: 600; }
@media (max-width: 40rem) {
  /* The phone shape: the nav wraps to its own row rather than squeezing the brand out. */
  .nav { flex-wrap: wrap; row-gap: var(--s2); }
  .navlink { padding-left: 0; padding-right: var(--s4); }
}



/* =======================================================================================
   THE SHARED COMPONENT LAYER (implemented from "EnergyMark App.dc.html", the design canvas)

   Originally scoped to the customer shell. Unscoped on the owner's call, so the desk and the
   supplier portal wear the same vocabulary rather than an older one. ONE system, TWO
   densities: the desk is tighter, because eighteen queue screens are read all day by people
   paid to be fast, and the customer app is roomier, because it is read once a year by
   somebody mildly anxious. The difference is padding and type scale, never colour, never
   component shape, and never what a state means.

   Scoped to .app-shell so none of it reaches the desk or the supplier portal, which are a
   deliberately different, denser thing and share the .nav shell above.

   The canvas is inline-styled throughout, as canvases are. It is reassembled here as
   classes because thirteen screens share these components, and thirteen copies of a card
   rule is how a design system stops being one.
   ===================================================================================== */

/* ---- the two-tier bar ---------------------------------------------------------------- */

.appbar { background: var(--brand-dark); color: #fff; }
.appbar-top { max-width: 1100px; margin: 0 auto; padding: 0 20px; min-height: 56px;
              display: flex; align-items: center; justify-content: space-between; gap: 20px; }
.appbar-brand { display: flex; align-items: center; gap: 9px; font-family: var(--display);
                font-size: 15px; font-weight: 700; letter-spacing: .02em; color: #fff;
                text-decoration: none; }
/* The wordmark carries the one piece of identity: a green bar, carrying no state. */
.appbar-mark { width: 9px; height: 18px; background: var(--accent-fill); border-radius: 1px; }
.appbar-who { display: flex; align-items: center; gap: 14px; }
.appbar-org { font-size: 12px; font-weight: 500; color: #c6d7e8; }
.avatar { width: 28px; height: 28px; border-radius: 50%; background: var(--brand);
          border: 1px solid #4a7db0; display: flex; align-items: center;
          justify-content: center; font-size: 11px; font-weight: 600; color: #fff; }

.appbar-row { border-top: 1px solid var(--brand); }
.appbar-nav { max-width: 1100px; margin: 0 auto; padding: 0 20px; display: flex;
              align-items: stretch; justify-content: space-between; gap: 16px;
              overflow-x: auto; }
.appbar-nav .group { display: flex; align-items: stretch; gap: 2px; }
.appbar-tab { position: relative; padding: 11px 12px 12px; font-size: 13px; font-weight: 600;
              color: #fff; white-space: nowrap; text-decoration: none; }
.appbar-tab.aside { color: #c6d7e8; }
/* The active tab is marked by a rule, not by colour alone, so it survives greyscale. */
.appbar-tab.on::after { content: ''; position: absolute; left: 12px; right: 12px; bottom: 0;
                        height: 3px; background: var(--accent-fill); }
.appbar-tab:hover { color: #fff; }

/* ---- page frame ---------------------------------------------------------------------- */

.app-shell { background: var(--ground); }
.app-page { max-width: 1100px; margin: 0 auto; padding: 28px 20px 80px; }
.app-page.narrow { max-width: 820px; }
.app-shell h1, .desk-shell h1 { font-size: 22px; font-weight: 600; margin: 0 0 4px; }
.app-shell h2, .desk-shell h2 { font-size: 15px; font-weight: 600; }
.sub { font-size: 13px; font-weight: 500; color: var(--ink-2); margin: 0 0 20px; }
.backlink { display: inline-block; font-size: 12px; font-weight: 600; color: var(--brand);
            margin-bottom: 10px; text-decoration: none; }
.backlink:hover { text-decoration: underline; }

/* The label above almost everything. Small, spaced, and never a heading level, because it
   labels a region rather than opening one. */
.eyebrow { font-size: 10px; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
           color: var(--ink-2); margin-bottom: 8px; }
.eyebrow.act { color: var(--accent); }
.eyebrow.warn { color: var(--warn); }
.eyebrow.bad { color: var(--bad); }

/* ---- cards and grids ------------------------------------------------------------------ */

.card { background: var(--paper); border: 1px solid var(--line); border-radius: 5px;
                   padding: 20px 22px; }
/* A card that is asking for something. The rule is on the leading edge so it reads down a
   stack of cards without competing with the state chips inside them. */
.card.asks { border-left: 4px solid var(--accent); }
.stack { display: flex; flex-direction: column; gap: 12px; }
.grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.grid.wide { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }

/* Numbers everywhere: system stack with tabular figures so columns line up and a digit
   never changes width as a value updates. Montserrat is for words. */
.num, .app-shell td.num, .stat-figure {
  font-family: var(--data); font-variant-numeric: tabular-nums; }
.stat-figure { font-size: 22px; font-weight: 600; }
.stat-note { font-size: 12px; font-weight: 500; color: var(--ink-2); margin-top: 4px; }

/* ---- the quiet state, which most of these screens are most of the time ----------------- */

.quiet { text-align: center; padding: 44px 28px; }
.quiet-mark { width: 34px; height: 34px; margin: 0 auto 16px; border-radius: 50%;
              border: 1px solid #cfe3d6; background: #f2f8f4; color: var(--good);
              display: flex; align-items: center; justify-content: center; font-size: 15px; }
.quiet-title { font-size: 19px; font-weight: 600; margin-bottom: 8px; }
.quiet p { font-size: 14px; font-weight: 500; line-height: 1.6; color: var(--ink-2);
           max-width: 460px; margin: 0 auto; text-wrap: pretty; }

/* ---- chips: four states, each with a mark as well as a colour -------------------------- */

.chip { display: inline-flex; align-items: center; gap: 6px; font-size: 11px;
                   font-weight: 600; padding: 3px 9px; border-radius: 3px;
                   background: var(--line-2); border: 1px solid var(--line);
                   color: var(--ink-2); }
.chip.good { background: var(--good-chip); border-color: var(--good-edge);
                        color: var(--good); }
.chip.warn { background: var(--warn-chip); border-color: var(--warn-edge);
                        color: var(--warn); }
.chip.bad  { background: var(--bad-wash); border-color: #e7c3c0; color: var(--bad); }
/* Undecidable keeps the dashed rule and NO fill: it has not failed and it has not passed. */
.chip.unknown { background: transparent; border: 1px dashed var(--unknown);
                           color: var(--unknown); }

/* ---- buttons --------------------------------------------------------------------------- */

.btn { background: var(--accent); color: #fff; font-family: var(--display);
                  font-size: 13px; font-weight: 600; padding: 9px 16px; border-radius: 4px;
                  border: 1px solid transparent; min-height: 0; }
.btn:hover { background: #15612a; }
.btn.ghost { background: var(--paper); color: var(--ink);
                        border-color: var(--ghost-edge); }
.btn.ghost:hover { border-color: var(--brand); background: var(--paper); }
.btn.big { font-size: 15px; padding: 13px 26px; }

/* ---- tables ----------------------------------------------------------------------------- */

.tablecard { background: var(--paper); border: 1px solid var(--line);
                        border-radius: 5px; overflow: hidden; }
.tablecard .scroller { overflow-x: auto; }
table.data { width: 100%; min-width: 660px; border-collapse: collapse; }
table.data thead tr { background: var(--ground); }
table.data th { text-align: left; font-size: 10px; font-weight: 600;
                           letter-spacing: .09em; text-transform: uppercase;
                           color: var(--ink-2); padding: 11px 18px;
                           border-bottom: 1px solid var(--line); }
table.data td { padding: 15px 18px; border-bottom: 1px solid var(--line);
                           vertical-align: top; font-size: 13px; font-weight: 500; }
table.data tbody tr:last-child td { border-bottom: 0; }
table.data tbody tr:hover { background: var(--hover); }
table.data th.num, table.data td.num { text-align: right; }
.rowlink { font-size: 14px; font-weight: 600; color: var(--brand); text-decoration: underline; }
.rowsub { font-family: var(--data); font-variant-numeric: tabular-nums; font-size: 12px;
          color: var(--ink-2); margin-top: 3px; }

/* ---- the price window, which is a real deadline ----------------------------------------- */

.decay { height: 6px; background: var(--line-2); border-radius: 3px; overflow: hidden; }
.decay > span { display: block; height: 100%; background: var(--warn); }
.decay-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
              margin-bottom: 6px; font-size: 11px; font-weight: 600; color: var(--warn); }
.price-figure { font-family: var(--data); font-variant-numeric: tabular-nums; font-size: 34px;
                font-weight: 600; line-height: 1; letter-spacing: -.01em; }
.price-figure small { font-size: 18px; font-weight: 500; }
.price-foot { padding: 24px 26px; background: var(--hover); }

/* ---- the switch tracker, as a timeline --------------------------------------------------- */

.tl { display: flex; flex-direction: column; }
.tl-step { display: flex; gap: 16px; }
.tl-rail { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center;
           width: 22px; }
.tl-dot { width: 22px; height: 22px; border-radius: 50%; display: flex; align-items: center;
          justify-content: center; font-size: 11px; font-weight: 700; background: var(--paper);
          border: 2px solid var(--line); }
.tl-line { flex: 1; width: 2px; background: var(--line); min-height: 26px; }
.tl-step:last-child .tl-line { display: none; }
.tl-body { padding-bottom: 22px; flex: 1; }
.tl-title { font-size: 15px; font-weight: 600; margin-bottom: 3px; }
.tl-body p { font-size: 13px; font-weight: 500; line-height: 1.55; color: var(--ink-2);
             margin: 0 0 12px; }
.tl-when { font-family: var(--data); font-variant-numeric: tabular-nums; font-size: 12px;
           color: var(--ink-2); }
.tl-step.done .tl-dot { background: var(--good); border-color: var(--good); color: #fff; }
.tl-step.done .tl-line { background: var(--good); }
/* Now: a ring rather than a fill, so the current step reads as open rather than finished. */
.tl-step.now .tl-dot { border: 3px solid var(--accent); }
.tl-step.stopped .tl-dot { background: var(--bad); border-color: var(--bad); color: #fff; }
.tl-step.later .tl-dot { border-color: var(--line); }
.tl-step.later .tl-title { font-weight: 500; color: var(--ink-2); }

/* ---- rate position: a position, never a saving -------------------------------------------- */

.rp-track { position: relative; height: 34px; }
.rp-base { position: absolute; left: 0; right: 0; top: 14px; height: 6px;
           background: var(--line-2); border-radius: 3px; }
.rp-range { position: absolute; top: 14px; height: 6px; background: var(--brand);
            border-radius: 3px; }
.rp-median { position: absolute; top: 9px; width: 2px; height: 16px; background: var(--paper); }
/* The customer's own mark is INK, never green and never red: it is a position, and a
   position carries no verdict. */
.rp-you { position: absolute; top: 2px; width: 3px; height: 30px; background: var(--ink);
          border-radius: 1px; }
.rp-scale { position: relative; height: 38px; margin-top: 2px; }
.rp-tick { position: absolute; transform: translateX(-50%); text-align: center; }
.rp-tick .v { font-family: var(--data); font-variant-numeric: tabular-nums; font-size: 12px;
              font-weight: 600; }
.rp-tick .k { font-size: 10px; font-weight: 600; color: var(--ink-2); letter-spacing: .04em;
              text-transform: uppercase; }
.rp-key { display: flex; align-items: center; gap: 8px; margin-top: 6px; font-size: 12px; }
.rp-key .swatch-you { width: 3px; height: 14px; background: var(--ink); border-radius: 1px; }
.rp-key .swatch-range { width: 16px; height: 6px; background: var(--brand); border-radius: 3px; }
.rp-key .sep { width: 1px; height: 12px; background: var(--line); margin: 0 4px; }
.rp-note { font-size: 12px; font-weight: 500; line-height: 1.6; color: var(--ink-2);
           margin: 20px 0 0; padding-top: 14px; border-top: 1px solid var(--line);
           max-width: 640px; }
/* Withheld is bounded by a dashed rule, the same signal the undecidable chip uses. */
.rp-withheld { border: 1px dashed var(--unknown); border-radius: 4px; padding: 18px 20px; }

/* ---- checklists ("what we hold", "what is in it") ------------------------------------------ */

.ticklist { display: flex; flex-direction: column; gap: 9px; }
.ticklist > div { display: flex; align-items: flex-start; gap: 9px; font-size: 13px;
                  font-weight: 500; line-height: 1.45; }
.ticklist .mark { line-height: 1.45; }
.ticklist .mark.yes { color: var(--good); }
.ticklist .mark.no  { color: var(--bad); }
.ticklist .mark.note { color: var(--warn); }

@media (max-width: 40rem) {
  .app-page { padding: 20px 16px 64px; }
  .appbar-top, .appbar-nav { padding: 0 16px; }
  .app-shell h1, .desk-shell h1 { font-size: 20px; }
  .price-figure { font-size: 28px; }
}


/* =======================================================================================
   DESK AND SUPPLIER DENSITY

   The same components as the customer app, tightened. Eighteen queue screens read all day by
   people paid to be fast need less air than one screen read once a year by somebody mildly
   anxious about money. What changes is padding and type scale. What does NOT change is
   colour, component shape, or what any state means, because a desk and a customer looking at
   the same deal have to be looking at the same thing.
   ===================================================================================== */

.desk-shell { background: var(--ground); font-size: 13px; }
.desk-bar .appbar-top { min-height: 48px; }
.desk-bar .appbar-tab { padding: 9px 11px 10px; font-size: 12px; }
.desk-shell h1 { font-size: 19px; font-weight: 600; margin: 0 0 4px; }
.desk-shell h2 { font-size: 14px; font-weight: 600; }
.desk-shell .page { max-width: 1240px; margin: 0 auto; padding: 22px 20px 64px; }
.desk-shell .card { padding: 16px 18px; margin-bottom: 12px; }
.desk-shell .btn { font-size: 12px; padding: 7px 13px; }
.desk-shell table.data { min-width: 0; }
.desk-shell table.data th { padding: 9px 14px; }
.desk-shell table.data td { padding: 10px 14px; font-size: 12px; }
.desk-shell .stat-figure { font-size: 19px; }
.desk-shell .eyebrow { margin-bottom: 6px; }

/* Cards on the desk sit in a grid far more often than a stack, because a work queue is
   several lists side by side rather than one narrative. */
.desk-shell .cards { display: grid; gap: 12px;
                     grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); }
.desk-shell .items { list-style: none; padding: 0; margin: 0; }
.desk-shell .items li { padding: 7px 0; border-bottom: 1px solid var(--line-2);
                        font-size: 12px; }
.desk-shell .items li:last-child { border-bottom: 0; }

/* The chip, reconciled. The desk version used a pill and a pseudo-element mark; the design
   uses a squarer chip with a bordered wash. The MARK stays as a pseudo-element rather than
   markup, because that is what guarantees a state is never colour alone: it cannot be left
   out of a template by accident. */
.chip { border-radius: 3px; font-family: var(--display); font-size: 11px; padding: 3px 9px;
        border: 1px solid var(--line); background: var(--line-2); align-items: center; }
.chip.good { background: var(--good-chip); border-color: var(--good-edge); }
.chip.warn { background: var(--warn-chip); border-color: var(--warn-edge); }
.chip.bad  { background: var(--bad-wash);  border-color: #e7c3c0; }
.chip.unknown { background: transparent; border: 1px dashed var(--unknown); }

/* Cards and tables carry the design's radius everywhere, so a screenshot of the desk and a
   screenshot of the customer app are recognisably the same product. */
.card, .tablecard { border-radius: 5px; }

@media (max-width: 40rem) {
  .desk-shell .page { padding: 16px 14px 56px; }
  /* Touch target. The design's button is ~33px, which clears the AA minimum of 24 and not
     the AAA target of 44, so a finger gets the larger one and a mouse gets the design. */
  .btn, .appbar-tab { min-height: 44px; display: inline-flex; align-items: center; }
}


/* =======================================================================================
   THE AUTH PAGES

   THREE shells reach this: allauth's (customer sign-in, sign-up, verification, password
   reset), Django's own (staff sign-in), and the 403 page. They were styled separately and
   drifted, which is how the staff door ended up a generation behind the customer one. It is
   stated once here and every shell points at it.

   Interim, pending the auth design brief. What it does is make the click from the landing
   page, to a sign-in, to the product look like one company rather than three.
   ===================================================================================== */

.auth-shell { min-height: 100vh; display: flex; flex-direction: column;
              background: var(--ground); font-family: var(--display); font-size: 14px;
              font-weight: 500; }
.auth-wrap { flex: 1; display: grid; place-items: center; padding: 32px 20px 64px; }
.auth { width: min(26rem, 100%); }
.auth .card { padding: 26px 24px; margin-bottom: 0; }
.auth h1 { font-size: 19px; font-weight: 600; margin: 0 0 6px; }
.auth form > p, .auth form > div { margin-bottom: var(--s4); }
.auth label { display: block; font-size: 12px; font-weight: 600; color: var(--ink-2);
              margin-bottom: 5px; }
.auth input[type=text], .auth input[type=email], .auth input[type=password] {
  width: 100%; font: inherit; font-size: 14px; padding: 9px 11px;
  border: 1px solid var(--ghost-edge); border-radius: 4px; background: var(--paper);
  color: var(--ink); }
.auth input:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px;
                            border-color: var(--brand); }
.auth button, .auth input[type=submit] {
  font-family: var(--display); font-size: 14px; font-weight: 600; padding: 11px 20px;
  border-radius: 4px; border: 0; background: var(--accent); color: #fff; cursor: pointer;
  width: 100%; }
.auth button:hover { background: #15612a; }
.auth .actions { margin-top: 0; }
.auth .helptext, .auth .helptext ul { font-size: 12px; color: var(--ink-2); }
.auth .errorlist { list-style: none; padding: 0; margin: 0 0 8px; font-size: 12px;
                   font-weight: 600; color: var(--bad); }
.auth hr { border: 0; border-top: 1px solid var(--line); margin: var(--s5) 0 var(--s4); }
.auth h2 { font-size: 10px; font-weight: 600; text-transform: uppercase;
           letter-spacing: .09em; color: var(--ink-2); margin-bottom: var(--s3); }
/* allauth renders the third-party options as a bare list of links. Make them read as the
   buttons people expect, stacked and full width. Ghost, not green: the green button is the
   primary action and a page has exactly one of those. */
.auth ul:has(a[href*="/login/?process"]) { list-style: none; padding: 0; margin: 0; }
.auth ul:has(a[href*="/login/?process"]) li { margin-bottom: var(--s2); }
.auth a[href*="/login/?process"] {
  display: block; text-align: center; text-decoration: none; font-size: 14px;
  font-weight: 600; padding: 10px 16px; border: 1px solid var(--ghost-edge);
  border-radius: 4px; background: var(--paper); color: var(--ink); }
.auth a[href*="/login/?process"]:hover { border-color: var(--brand); }
.auth-foot { font-size: 12px; font-weight: 500; color: var(--ink-2); margin-top: 14px;
             text-align: center; }
